gpt4 book ai didi

java - 如何安全地序列化 lambda?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:43:06 26 4
gpt4 key购买 nike

虽然it is possible to serialize a lambda in Java 8 , 它是 strongly discouraged ;甚至 serializing inner classes is discouraged .给出的原因是 lambda 可能无法在另一个 JRE 上正确反序列化。然而,这是否意味着有一种安全序列化 lambda 的方法?

例如,假设我定义一个类是这样的:

public class MyClass {
private String value;
private Predicate<String> validateValue;

public MyClass(String value, Predicate<String> validate) {
this.value = value;
this.validateValue = validate;
}

public void setValue(String value) {
if (!validateValue(value)) throw new IllegalArgumentException();
this.value = value;
}

public void setValidation(Predicate<String> validate) {
this.validateValue = validate;
}
}

如果我这样声明一个类的实例,我不应该序列化它:

MyClass obj = new MyClass("some value", (s) -> !s.isEmpty());

但是如果我像这样创建一个类的实例会怎样:

// Could even be a static nested class
public class IsNonEmpty implements Predicate<String>, Serializable {
@Override
public boolean test(String s) {
return !s.isEmpty();
}
}
MyClass isThisSafeToSerialize = new MyClass("some string", new IsNonEmpty());

现在序列化是否安全?我的直觉告诉我,是的,它应该是安全的,因为没有理由将 java.util.function 中的接口(interface)与任何其他随机接口(interface)区别对待。但我仍然很谨慎。

最佳答案

这取决于你想要哪种安全。序列化的 lambda 并不是不能在不同的 JRE 之间共享的情况。它们有一个定义明确的持久表示,SerializedLambda .当您研究它的工作原理时,您会发现它依赖于定义类的存在,该定义类将有一个特殊的方法来重构 lambda。

它不可靠的原因是依赖于编译器特定的工件,例如合成目标方法,它有一些生成的名称,因此插入另一个 lambda 表达式或使用不同的编译器重新编译类等简单的更改可能会破坏与现有序列化 lambda 表达式的兼容性。

但是,使用手动编写的类并不能避免这种情况。如果没有显式声明的 serialVersionUID,默认算法将通过散列类工件(包括 private 和合成工件)来计算 id,添加类似的编译器依赖性。因此,如果您想要可靠的持久形式,至少要做的是声明一个显式的 serialVersionUID

或者您转向可能的最健壮的形式:

public enum IsNonEmpty implements Predicate<String> {
INSTANCE;

@Override
public boolean test(String s) {
return !s.isEmpty();
}
}

序列化此常量不存储实际实现的任何属性,除了它的类名(当然还有它是一个 enum 的事实)和对常量名称的引用。反序列化后,将使用该名称的实际唯一实例。


请注意 serializable lambda expressions may create security issues因为它们打开了另一种获取允许调用目标方法的对象的方法。但是,这适用于所有可序列化类,因为您的问题和此答案中显示的所有变体都允许故意反序列化允许调用封装操作的对象。但是对于显式可序列化类,作者通常更清楚这一事实。

关于java - 如何安全地序列化 lambda?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38018415/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com