可序列化的Java Lambda

这一篇文章,可以帮助您解决在尝试使用Kryo序列化lambda时可能发生的特定错误。

最近,当用Kryo序列化lambda时,出现以下错误:


可序列化的Java Lambda

如果您不了解(Runnable & Serializable)语法,请放心,它只是说明lambda必须实现两种类型。这称为类型交集。就我个人而言,我从来不需要自己使用它,因此也从未真正考虑过它。Serializable在这方面,它是一个独特的接口,因为您实际上不需要实现。

如果不执行此强制转换,则lambda将被视为无法序列化,这不会使Kryo满意。

作为一个不经常查看字节码的人,我发现在添加和额外转换时,它们之间的巨大差异令人惊讶& Serializable。下面的示例演示了这一点。为了清楚起见,我使用以下命令从代码段生成字节码:


可序列化的Java Lambda

在进行任何投射之前:


可序列化的Java Lambda

生成的字节码为:


可序列化的Java Lambda

投放后:


可序列化的Java Lambda

字节码变为:


可序列化的Java Lambda


可序列化的Java Lambda


可序列化的Java Lambda


可序列化的Java Lambda

现在,我真的不知道如何读取字节码,但是即使我可以看到,使用强制转换的版本中还有很多事情要做& Serializable。

如果您能解释那里发生的事情,请成为我的客人,并大声喊叫我。

我可以从上面的字节码中读取一件事,就是SerializedLambda以前没有的引用。编译器和库使用此类来确保lambda正确地反序列化。使交集转换为Function<string> & Serializable/<string>

添加额外的转换& Serializable是允许Kryo反序列化lambda的一种可能解决方案。另一种方法是创建一个新接口,以扩展所需的基础Function类型以及Serializable

您可以使用以下界面:

可序列化的Java Lambda

然后可以使用它来替换上一个示例中的铸件:

可序列化的Java Lambda

我在下面添加了此更改生成的字节码:

可序列化的Java Lambda


可序列化的Java Lambda


可序列化的Java Lambda


可序列化的Java Lambda

大部分相同,只是对SerializableLambda接口有一些新的引用,并删除了原始的交集。

如前所述,该解决方案非常适合库和API作者,因为它使开发人员能够照常编写代码,而不必担心转换(例如,如果库在后台使用Kryo)。此外,由于接口扩展Function为a @FunctionalInterface,因此开发人员可以很好地编写lambda /函数,并且如果将其直接传递给另一个函数或构造函数,甚至不必提及该接口。在为Corda设计新的API时,我个人遵循了这条路线

总而言之,在这篇文章中,它缺少大量信息,并且充斥着扩展的字节码片段,您需要拿走两件事。您可以使Java lambda / function通过类型交集可序列化,并且可以通过创建扩展所需函数类型和的新接口来确保自己的API干净Serializable。当使用诸如Kryo之类的序列化库时,这两个路由都应考虑。

如果您喜欢这篇文章或发现它有帮助(或两者都有),请随时关注我,并记得与其他可能觉得有用的人分享!


分享到:


相關文章: