首页
/ Apache Fury Scala 对象反序列化问题解析

Apache Fury Scala 对象反序列化问题解析

2025-06-25 09:01:25作者:董灵辛Dennis

问题背景

在使用 Apache Fury 进行 Scala 对象序列化/反序列化时,开发人员发现了一个特殊现象:当尝试反序列化一个 Scala 的 case object 或单例对象时,首次反序列化会返回 null 值,而只有在执行过一次序列化操作后,后续的反序列化才能正常工作。

问题复现

这个问题在以下两种场景中表现明显:

  1. 简单 case class 场景:定义一个简单的 case class 并尝试反序列化其序列化后的字节数组,首次反序列化返回 null,执行一次序列化操作后,再次反序列化才能得到正确结果。

  2. Scala 枚举模式场景:使用 sealed trait 和 case object 实现的枚举模式,当修改枚举值后重新运行程序,反序列化会返回 null 而不是预期的枚举值。

技术分析

经过深入分析,发现问题的根源在于 Scala 对单例对象(object)的懒加载机制。Scala 中的单例对象是延迟初始化的,只有在首次被访问时才会真正创建实例。这种设计导致了以下行为:

  1. 当 Fury 的 SingletonObjectSerializer 尝试读取单例对象时,如果该对象尚未被初始化,其 MODULE$ 字段可能为 null 或者根本不存在。

  2. 只有在程序显式引用了该单例对象(如执行序列化操作时),Scala 运行时才会初始化该对象,设置 MODULE$ 字段。

  3. 这就是为什么首次反序列化失败,而执行序列化后反序列化却能成功的原因——序列化操作隐式触发了单例对象的初始化。

解决方案

针对这个问题,社区提出了一个优雅的解决方案:在 SingletonObjectSerializer 的构造函数中,主动检查并确保目标类已完成初始化。具体实现是通过 Java 的 Unsafe API 来强制初始化目标类:

public SingletonObjectSerializer(Fury fury, Class type) {
  super(fury, type);
  if (Platform.UNSAFE.shouldBeInitialized(type)) {
    Platform.UNSAFE.ensureClassInitialized(type);
  }
  try {
    field = type.getDeclaredField("MODULE$");
  } catch (NoSuchFieldException e) {
    throw new RuntimeException(type + " doesn't have `MODULE$` field", e);
  }
}

这个修改确保了在访问 MODULE$ 字段之前,目标类已经完全初始化,从而解决了首次反序列化返回 null 的问题。

技术启示

这个问题给我们几个重要的技术启示:

  1. 理解语言特性:在使用序列化框架时,必须深入理解目标语言的特性,如 Scala 的单例对象懒加载机制。

  2. 框架适配:通用序列化框架需要针对不同语言的特性进行特殊处理,不能假设所有语言的对象初始化行为都一致。

  3. 防御性编程:在访问可能延迟初始化的资源时,应该采用防御性编程策略,确保资源可用后再进行操作。

这个问题的解决不仅修复了 Apache Fury 在 Scala 环境下的一个关键问题,也为处理类似的语言特性与序列化框架的交互提供了有价值的参考。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
24
9
nop-entropynop-entropy
Nop Platform 2.0是基于可逆计算理论实现的采用面向语言编程范式的新一代低代码开发平台,包含基于全新原理从零开始研发的GraphQL引擎、ORM引擎、工作流引擎、报表引擎、规则引擎、批处理引引擎等完整设计。nop-entropy是它的后端部分,采用java语言实现,可选择集成Spring框架或者Quarkus框架。中小企业可以免费商用
Java
9
1
leetcodeleetcode
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Java
64
19
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
392
3.88 K
flutter_flutterflutter_flutter
暂无简介
Dart
671
156
giteagitea
喝着茶写代码!最易用的自托管一站式代码托管平台,包含Git托管,代码审查,团队协作,软件包和CI/CD。
Go
23
0
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
JavaScript
260
322
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
661
311
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
1.2 K
654
rainbondrainbond
无需学习 Kubernetes 的容器平台,在 Kubernetes 上构建、部署、组装和管理应用,无需 K8s 专业知识,全流程图形化管理
Go
15
1