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

时间:2016-02-10 12:09:45

标签: akka deserialization classloader akka-remote-actor

我正在尝试设置一个Akka系统,其中反序列化错误会触发一个交换缺失类的协议。我为此目的使用自定义de / serializer,一旦捕获到与缺少类相关的异常,就会向应用程序actor返回某个消息。

简单来说,远程系统B将对象发送给系统A;如果在反序列化期间,系统A获得 ClassNotFoundError NoClassDefFoundError ,则系统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< ==== X?==== A(A问X到B级)
  • 4)B ===== X ====> B(B提供类X到A; A注册类X)
  • 5)B === obj:X ==> A(由于缺少依赖关系Y而导致错误)
  • 6)B< ==== Y?==== A
  • 7)B ===== Y ====> A(A登记类Y)
  • 8)B === obj:X ==> A
  • 9)B< ==== Z?==== A
  • 10)B ===== Z ====> A(A登记类Z)
  • 10)B === obj:X ==> A(好的,最后A可以反序列化X类的对象)

我认为这样的协议应该有效,但实际上我会在步骤5-7中得到一个循环,原因如下

NoClassDefFoundError:Lexamples / DemoDecentralizedAkkaPlatformCmdLineMain2 $ AggregateProgram $$ anonfun $ main $ 3 $$ anonfun $ apply $ 5;

我要注册以下课程: examples.DemoDecentralizedAkkaPlatformCmdLineMain2 $ AggregateProgram $$ anonfun $ main $ 3 $$ anonfun $ apply $ 5

然而我一直得到NoClassDefFoundError。

请注意,我删除了初始“L”和尾随“;”从类名,以及用“。”替换“/”。否则,我会在系统B上收到错误。

对于这样复杂的问题表达,我很抱歉。

1 个答案:

答案 0 :(得分:0)

摘要概述:

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

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