List.of()的坑——不能够序列化

List.of()的坑——不能够序列化

场景:在dubbo接口中返回了空集合是使用了List.of() 方法创建了个空的集合,放入到响应数据中

报错信息如下:

Exception in thread "main" com.alibaba.com.caucho.hessian.io.HessianFieldException: com.demo.SerializeTest$ResponseDto.data: java.util.CollSer:java.lang.reflect.InvocationTargetException
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer.logDeserializeError(JavaDeserializer.java:168)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer$ObjectFieldDeserializer.deserialize(JavaDeserializer.java:415)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:277)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:204)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2848)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2175)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2104)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2148)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2104)
	at org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectInput.readObject(Hessian2ObjectInput.java:101)
	at com.demo.SerializeTest.main(SerializeTest.java:32)
Caused by: com.alibaba.com.caucho.hessian.io.IOExceptionWrapper: java.util.CollSer:java.lang.reflect.InvocationTargetException
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:291)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:204)
	at com.alibaba.com.caucho.hessian.io.SerializerFactory.readObject(SerializerFactory.java:548)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2850)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2773)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2308)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2747)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2308)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2110)
	at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2104)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer$ObjectFieldDeserializer.deserialize(JavaDeserializer.java:411)
	... 9 more
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer.resolve(JavaDeserializer.java:300)
	at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:282)
	... 19 more
Caused by: java.io.InvalidObjectException: null array
	at java.base/java.util.CollSer.readResolve(ImmutableCollections.java:1091)
	... 25 more

Process finished with exit code 1

从报错信息中发现使用了Hessian2Input.readObject()方法时报错,模拟下报错的场景,复现下问题
模拟代码:

import com.tianrui.base.response.ResponseDTO;
import lombok.Data;
import org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectInput;
import org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectOutput;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class SerializeTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // m1();
        List<Student> data = List.of();
        // data = new ArrayList<>();
        ResponseDto<List<Student>> responseDto = new ResponseDto<>(data);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        Hessian2ObjectOutput hessian2ObjectOutput = new Hessian2ObjectOutput(byteArrayOutputStream);
        hessian2ObjectOutput.writeObject(responseDto);
        hessian2ObjectOutput.flushBuffer();
        var s = new Hessian2ObjectInput(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())).readObject(responseDto.getClass());

        System.out.println(s);

    }

    @Data
    public static class ResponseDto<T> implements Serializable {
        private static final long serialVersionUID = -2354066777812251826L;

        private T data;

        public ResponseDto(T data) {
            this.data = data;
        }
    }

    @Data
    public static class Student implements Serializable{
        private static final long serialVersionUID = 6322616407817236979L;
        private String name;

        public Student(String name) {
            this.name = name;
        }
    }
}

当List data 使用 List.of() 赋值一个空集合时,报错信息复现,使用 new ArrayList<>() 的方式赋值一个空集合时,报错消失。问题解决了,比较下 List.of() 和 new ArrayList<>() 有什么区别?

List.of() 源码

    static <E> List<E> of() {
        return ImmutableCollections.emptyList();
    }

ImmutableCollections.emptyList()的源码:

    @SuppressWarnings("unchecked")
    static <E> List<E> emptyList() {
        return (List<E>) ListN.EMPTY_LIST;
    }

(List) ListN.EMPTY_LIST; 源码:

    static final class ListN<E> extends AbstractImmutableList<E>
            implements Serializable {

        static final List<?> EMPTY_LIST = new ListN<>();

        @Stable
        private final E[] elements;

static final List<?> EMPTY_LIST = new ListN<>(); 源码;
这个 ListN 的类虽然实现了 Serializable 序列化接口,但是并没有 声明 serialVersionUID,因此无法进行序列化
在看下ArrrayList的源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码到成功>_<

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值