扩展Hessian早期版本反序列化,使其支持jdk8可序列化lambda表达式

尝试扩展Hessian早期版本反序列化,使其支持jdk8可序列化lambda表达式

引出

dubbo版本2.5.3
内置默认序列化hessian.io 在调用传参有函数接口时,客户端序列化失败。

// 无法序列化的字段
private Predict<T> bar = any -> true;

原因是Predict并未实现Serializable,自定义实现后,

@FunctionalInterface
public interface SerializablePredict<T> extends Predict<T>, Serializable {
   }

客户端不报错,服务端反序列化失败。
原因是序列化时,上述对象会被序列化成SerializedLambda的一个实例,显然服务端hessian没有处理该对象的反序列化实现,而使用默认反序列化器JavaDeserializer,最后报错。

解决

1. 实现反序列化逻辑

gayhub搜最新的hessian源码,本期望有实现直接拷过来即可,结果源码里搜关键字Lambda没看到半行代码(也可能有用到jdk默认实现,隐藏到默认逻辑中了),那自己弄个吧。

本质上函数在内存中的存在是SerializedLambda,我们需要反序列化成这个类的对象,可以复用hessian已有的JavaDeserializer

@Component
public class LambdaDeserializer extends AbstractDeserializer {
   
    
    private static JavaDeserializer serializableLambdaDeserializer =
            new JavaDeserializer(HessianAdaptSerializedLambda.class);

    @Override
    public Object readObject(AbstractHessianInput in) throws IOException {
   
        return serializableLambdaDeserializer.readObject(in);
    }


    @Override
    public Object readMap(AbstractHessianInput in) throws IOException {
   
        return serializableLambdaDeserializer.readMap(in);
    }

    @Override
    public Object readObject(AbstractHessianInput in, String[] fieldNames) throws IOException {
   
        return serializableLambdaDeserializer.readObject(in, fieldNames);
    }
    
}

hessian反序列化pojo的逻辑是,先new一个,构造器需要入参则传默认值进去,再给属性赋值。
这导致SerailizedLambda这个类在反序列化时会遇到两个问题:

  1. 构造方法要求capturedArgs非空,但是hessian new的时候会传默认值,即null进去引起空指针
  2. 所有属性没有赋值方法

这玩意儿是final class,所以要自己拷改一个

import lombok.Data;
import lombok.AllArgsConstructor;

import java.io.Serializable;
import java.lang.invoke
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值