首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当lambda用于接口实现时“无效的lambda反序列化”

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

Stack Overflow用户
提问于 2015-03-09 16:10:56
回答 2查看 5.9K关注 0票数 4

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

代码语言:javascript
运行
复制
java.lang.IllegalArgumentException: Invalid lambda deserialization
at x.y.z.MyPage$3.$deserializeLambda$(MyPage.java:1)

在页面类(我返回的地方)中,我使用lambda表达式来实现这个接口:

代码语言:javascript
运行
复制
public interface Localizator extends Serializable {
    String getLocalizedString(String key);
}

而羔羊:

代码语言:javascript
运行
复制
protected void someMethod() {
    localize((String key) -> getString(key));
}

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

环境: Java 1.8.0_25,Netbeans 8.0.2,Wicket 6.17.0。

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

代码语言:javascript
运行
复制
@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() {
            ...
        }

    };
}

转换器级:

代码语言:javascript
运行
复制
public class Converter implements Serializable { 
    public static ArrayList asRowList(List data, OtherLoader loader, Localizator localizator){...}

DataLoader还扩展了可序列化。

EN

回答 2

Stack Overflow用户

发布于 2015-03-10 09:36:50

要启用Serialization支持,拥有一个interface扩展Serializable就足够了。没有必要再做一个额外的演员。这表现在代码可以序列化lambda表达式实例。反序列化失败了,因为反序列化是类不兼容的指示器,所以如果插入强制转换很可能会产生副作用,因为插入强制转换强制重新编译包含lambda表达式的类。

如果您想继续使用序列化的lambda,您应该了解它是如何工作的,正如SerializedLambda中所解释的那样。

可序列化lambda的实现者(例如编译器或语言运行库)将确保实例正确反序列化。这样做的一种方法是确保writeReplace方法返回SerializedLambda的实例,而不是允许进行默认序列化。 SerializedLambda有一个readResolve方法,它在捕获类中寻找一个(可能是私有的)静态方法$deserializeLambda$(SerializedLambda),用它本身调用它作为第一个参数,并返回结果。实现$deserializeLambda$的Lambda类负责验证SerializedLambda的属性是否与该类实际捕获的lambda一致。

因此,当$deserializeLambda$在异常情况下拒绝反序列化时,这意味着序列化lambda的属性与类中定义的已知可序列化lambda的属性不匹配。这些财产可能会变得非常脆弱。

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

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

票数 8
EN

Stack Overflow用户

发布于 2021-02-17 13:48:40

这没有回答上面的问题,但是在搜索Invalid lambda deserialization in Flink__时,这个线程首先弹出。

如果您在发布之前使用Proguard混淆

  • Proguard搞乱了Serializable
  • 您需要配置proguard.pro来修复此错误,请参阅这个答案

在我自己的例子中,我实现了正式文件中建议的“Java8Lambda”设置,但是文档改变了,现在我缺少了在这里解释的新设置。

一般情况下,"lambda不能序列化“是什么意思:

  • 这个lambda:.map(string -> (CustomClass) string)
  • 如果CustomClassimplement Serializable,则不可序列化。

若要使该类可序列化,请添加implements Serializable,并添加SerialVersionUID并确保该类的所有属性本身都可序列化。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28946655

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档