【发布时间】:2018-01-03 16:19:26
【问题描述】:
我已经阅读了关于这个一般性主题的各种旧 StackOverflow 讨论,但至少在我看来,这个谜题的一部分仍然缺失。
很简单:匿名函数序列化的实际机制是什么?而且,我们在哪里可以找到它的源代码?
或者这一切只是魔法?
其他相关的 SO 文章(其中第三篇本身指向 StockOverflow 之外的一些有用文章):
【问题讨论】:
标签: scala serialization
我已经阅读了关于这个一般性主题的各种旧 StackOverflow 讨论,但至少在我看来,这个谜题的一部分仍然缺失。
很简单:匿名函数序列化的实际机制是什么?而且,我们在哪里可以找到它的源代码?
或者这一切只是魔法?
其他相关的 SO 文章(其中第三篇本身指向 StockOverflow 之外的一些有用文章):
【问题讨论】:
标签: scala serialization
我将用什么来回答我自己的问题,我相信这是正确的答案。我这样做的原因是,在我看来,序列化的这一方面从未被解释过,而且它似乎只是靠魔法起作用。作为我正在做的研究的一部分,我基本上确认了答案(令我满意),以确保我的上述问题确实是合适的。
但我提供自己的答案的主要原因是我邀请知识渊博的用户同意它、纠正它、扩展它或破坏它。来了……
这一切都是魔法。不,我只是在开玩笑。但本质上,一旦 Scala 采取了将匿名函数表示为类的步骤,该机制完全由 Java 提供。此外,我们程序员需要确保匿名函数尽可能是纯代码:不引用任何可能无法序列化的对象。秘诀可以在 Java 类中找到:ObjectStreamClass。依次由 Java 序列化类调用:ObjectInputStream 和 ObjectOutputStream。
基本上,序列化字节包含类的完整路径名、它的serialVersionUID,以及任何其他必要的相关信息。反序列化时,系统将简单地查找适当类路径中的类并返回对它的引用。这显然假设反序列化系统在其类路径中具有该类。其机制有点超出我的研究范围,但很明显,在像 Spark 这样的系统中,它应该很容易安排。
不需要(额外的)字节码编译/反编译,因为类加载器拥有一切必要的东西。在 java.io 中而不是在反射包中找到 ObjectStreamClass 让我有点惊讶,但我想有一个论点,因为它与 ObjectInputStream 和 ObjectOutputStream。
要记住的一点是,虽然我们考虑的是序列化/反序列化 objects,而不是 classes,但我们在这里处理的是一个对象输入类。
还有一点需要注意的是,在 Scala 2.12 中,匿名函数现在以不同的方式实现:作为 Java8 lambda。这以相当严重的方式破坏了上述机制。如此严重,以至于 Spark 目前无法支持 Scala 2.12。滞留似乎是这个问题:SPARK-14540。
【讨论】: