当前位置: 首页 > 知识库问答 >
问题:

lambda用于接口实现时“无效lambda反序列化”

史良哲
2023-03-14

我有一个带有lambda表达式的wicket项目。在一个页面上,当用户单击“后退”按钮时,我的应用程序崩溃:

java.lang.IllegalArgumentException: Invalid lambda deserialization
at x.y.z.MyPage$3.$deserializeLambda$(MyPage.java:1)

在page类(返回的地方)中,我使用lambda表达式实现此接口:

public interface Localizator extends Serializable {
    String getLocalizedString(String key);
}

以及lambda:

protected void someMethod() {
    localize((String key) -> getString(key));
}

当我将lambda更改为匿名类时,一切正常。在这种情况下,我应该如何使用lambda?

环境:Java1.8。0_25,网豆8.0.2,Wicket 6.17.0。

编辑:这是使用lambda的真实(但简化)方法:

@Override
protected DataLoader createDataLoader() {

    return new DataLoader(){

        @Override
        public List loadData() {
            ...
        }

        @Override
        public List convertToTableRows(List data) {
            return Converter.asRowList(
                data, 
                (Record record) -> {...}, // this lambda is OK
                (String key) -> getString(key)); // this lambda is crashing
        }

        @Override
        public List filterTableRow() {
            ...
        }

    };
}

转换器类:

public class Converter implements Serializable { 
    public static ArrayList asRowList(List data, OtherLoader loader, Localizator localizator){...}

DataLoader还扩展了Serializable。

共有2个答案

锺宜
2023-03-14

这并没有回答上面的问题,但是在Flink中搜索无效的lambda反序列化时首先弹出此线程。

如果在发布前使用Proguard进行模糊处理:

>

你需要配置proguard.pro来修复这个错误,看这个答案。

在我自己的情况下,我实现了“Java8 Lambda”设置,建议在官方留档一段时间后,但留档改变了,现在我错过了那里解释的更新的设置。

孟彦
2023-03-14

要启用序列化支持,拥有一个扩展的可序列化接口就足够了。那么就不需要再做一次演员阵容了。代码可以序列化lambda表达式实例这一事实表明了这一点。反序列化时失败,这是类不兼容的指标,因此如果插入强制转换有帮助,很可能是一种副作用,因为插入强制转换会强制重新编译包含lambda表达式的类。

如果要继续使用序列化lambda,应了解其工作原理,如SerializedLambda的文档所述:

可序列化lambda的实现者(如编译器或语言运行库)应确保实例正确反序列化。这样做的一种方法是确保writeReplace方法返回SerializedLambda的实例,而不是允许进行默认序列化。

SerializedLambda有一个readResolve方法,该方法在捕获类中查找名为deserializeLambda$(SerializedLambda)的静态方法(可能是私有的),将其自身作为第一个参数调用,并返回结果。实现反序列化Lambda$的Lambda类负责验证序列化Lambda的属性是否与该类实际捕获的Lambda一致。

因此,当反序列化lambda$异常拒绝反序列化时,这意味着序列化lambda的属性与类中定义的已知可序列化lambda的属性不匹配。这些特性可能非常脆弱。

它们包括函数接口、捕获的参数和目标方法。对于lambda表达式(而不是方法引用),目标方法是定义类中的合成方法,选择了编译器,未指定的名称甚至可能依赖于同一类中的其他lambda表达式,因为插入另一个表达式可能会因编号方案而导致名称更改。

与普通类不同,在普通类中插入serialVersionUID可能会告诉序列化框架它不应该关心明显的不一致,您不能告诉lambda表达式显示更健壮的性能。换句话说,一旦序列化了应该持久化的lambda实例,就不能更改它们的定义类。另请参见此答案

 类似资料:
  • Eclipse JDT编译器似乎有一个问题,在某些情况下,Java8个lamda没有正确反序列化,而是抛出一个。我正在使用最近的分布式维护版本,如下所示: 现有的bug/SO条目报告了在中已经(至少部分)解决的类似问题。我亲自验证了以下问题已经得到解决。 无法反序列化访问实例字段和方法的Java 8 lambda https://bugs.eclipse.org/bugs/show_bug.cgi

  • 问题内容: 作为一个小项目,我一直在尝试做一个小事,它可以读取序列化的lambda(从本地或从FTP)并调用它们的运行函数作为测试的一部分,以测试Windows中的文件关联(即打开某些文件类型)使用特定程序打开它们),但不管如何,无论如何,它似乎从未正确地反序列化。 lambda被这样声明 并使用由ObjectOutputStream包装的[n可选] BufferedOutputStream包装的

  • 作为一个小项目,我一直在尝试制作一个小东西来读取序列化的lambda(本地或从FTP)并调用它们的run函数,作为测试的一部分,以在Windows中试验文件关联(即打开某些文件类型会用某个程序打开它们)等等,但无论我尝试什么,它似乎都无法正确地反序列化。 lambda是这样宣布的 并使用由ObjectOutputStream包装的[n可选]BufferedOutputStream包装的FileOu

  • 我正在玩弄一个基本的无限泛集群,我遇到了一个令人费解的错误。 我基本上实现了一个共享映射,只包含一个整数 这是我的服务代码 缓存是通过以下方式生成的: 当集群中至少有两台服务器时,computeIfAbsen会失败 这可以归结为: 最后是: 如果我把我非常好的时髦代码重写成丑陋的代码,它就会起作用。 我怎么能使用漂亮的电脑现在没有做事的方式? Eclipse 2018-12、WildFly 14、

  • 问题内容: 相当于kotlin中的代码,我尝试执行的操作似乎无效: 在里面: 问题答案: 如果是Java,则可以使用SAM转换: 否则,如果界面是Kotlin … …您可以使用语法匿名实现它:

  • 有没有人成功地为 S3 事件实施了基于 Java 的请求处理程序? 我的班级: 错误消息: JSON 解析期间发生错误:java.lang.RuntimeException java.lang.RuntimeException:JSON 解析期间发生错误 由以下原因引起:java.io.UncheckedIOException: com.fasterxml.jackson.databind.Jso