0

我正在尝试设置一个 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 <====X?==== A (A 向 B 询问班级 X)
  • 4)B =====X====> B(B向A提供X类;A注册X类)
  • 5) B ===obj:X==> A (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(OK,终于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 上收到错误。

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

4

1 回答 1

0

从抽象概述:

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

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

于 2016-04-22T15:08:41.587 回答