Akka中的反序列化和类加载-NoClassDefFoundError

Akka中的反序列化和类加载-NoClassDefFoundError,akka,deserialization,classloader,akka-remote-actor,Akka,Deserialization,Classloader,Akka Remote Actor,我正在尝试设置一个Akka系统,反序列化错误触发一个协议,在该协议中交换丢失的类。为此,我使用了一个定制的反序列化程序,一旦捕获到与缺少的类相关的异常,它就会向应用程序参与者返回一条特定的消息 简单来说,远程系统B向系统A发送一个对象;如果在反序列化过程中,系统A获得ClassNotFoundError或NoClassDefFoundError,则系统A向系统B请求未定义类的字节码。当A从B(一对类名加上类型为Array[Byte]的对象)接收到响应时,它可以注册该类,以便下次系统B将该对象发送

我正在尝试设置一个Akka系统,反序列化错误触发一个协议,在该协议中交换丢失的类。为此,我使用了一个定制的反序列化程序,一旦捕获到与缺少的类相关的异常,它就会向应用程序参与者返回一条特定的消息

简单来说,远程系统B向系统A发送一个对象;如果在反序列化过程中,系统A获得ClassNotFoundErrorNoClassDefFoundError,则系统A向系统B请求未定义类的字节码。当A从B(一对类名加上类型为Array[Byte]的对象)接收到响应时,它可以注册该类,以便下次系统B将该对象发送给系统A时,A可以正确地对其进行反序列化

现在,有两种方法

1) 系统B还发送与请求的类相关的所有类

2) 系统B只发送所请求类的字节码(不包含其依赖项)

现在,让我们关注方法2,考虑下面的场景

  • 1) B===obj:X==>A(B将类X的对象发送给A)
  • 2) 假设X依赖于Y,Z
  • 3) B(B向A提供X类;A注册X类)
  • 5) B===obj:X==>A(A由于缺少依赖项Y而获取错误)
  • 6) B A(A寄存器Y类)
  • 8) B===obj:X==>A
  • 9) B A(A类寄存器Z)
  • 10) B===obj:X==>A(好的,最后A可以反序列化类X的对象)
我认为这样的协议应该有效,但实际上我在步骤5-7中得到了一个循环,原因如下

NoClassDefFoundError:Lexamples/DemocentralizedAkaplatformCmdlineMain2$AggregateProgram$$anonfun$main$3$$anonfun$apply$5

我可以注册以下类:examples.demodecentralizedkkaplatformcmdlinemain2$AggregateProgram$$anonfun$main$3$$anonfun$apply$5

然而,我不断得到NoClassDefFoundError

请注意,我从类名中去掉了首字母“L”和尾随“;”,并将“/”替换为“.”。否则,我将在系统B上得到一个错误


很抱歉,这个问题的表述如此复杂。

从抽象概述:

加载类“X”时出现“NoClassDefFound Y”错误后,是否确保丢弃类加载器“X”,并在新的类加载器中加载“A”,其中包括字节码“Y”。如果一个类get被加载,但加载失败,JVM会记住错误并重新抛出它。至少对于某些类初始化错误。因此,您需要在新的类加载器中尝试重新加载

诚实的建议: 如果您试图创建一个可靠的分布式系统,请避免依赖精确的字节共享字节码或发送您的字节码。这将使系统变得非常脆弱。充其量只是奇怪的类装入器错误、方法未找到错误、序列化错误。最糟糕的情况是,您的系统运行的是不可见的、意外的代码:就像您部署了一个新版本,但它从仍在运行的其他实例加载了旧代码。 使用一些可靠的、独立于字节码的序列化。从众多序列化格式中选择一种。Akka已经带来了一个包含的。而且很容易包含另一个