环境:
win10 + jdk 1.8 + dubbo 2.5.10
问题描述:
当一个对象(此对象内包含多个CopyOnWriteArrayList对象) 作为参数调用RPC接口后, 服务提供者拿到的对象中的CopyOnWriteArrayList, 引用都相同了(即变成了同一个对象).
问题范围缩小:
Dubbo Serialization 反序列化时会有此问题, 用一下代码可以重现问题
import com.alibaba.dubbo.common.serialize.support.dubbo.GenericObjectInput; import com.alibaba.dubbo.common.serialize.support.dubbo.GenericObjectOutput; import java.io.*; /** * * Dubbo序列化的一个坑 * @author yjy * 2018-07-25 10:28 */ public class SerializerTest { public static void main(String[] args) throws IOException { Entity entity = new Entity(); // 此时两个 CopyOnWriteArrayList 不同 System.out.println(entity.getList1() == entity.getList2()); // 序列化 OutputStream outputStream = new FileOutputStream("dubboSerializer"); GenericObjectOutput objectOutput = new GenericObjectOutput(outputStream); objectOutput.writeObject(entity); objectOutput.flushBuffer(); // 反序列化 GenericObjectInput input = new GenericObjectInput(new FileInputStream("dubboSerializer")); Entity obj1 = (Entity) input.readObject(); // 此时两个 CopyOnWriteArrayList 相同???????????????????????? System.out.println(obj1.getList1() == obj1.getList2()); } }
import java.io.Serializable; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; /** * @author yjy * 2018-07-25 10:28 */ public class Entity implements Serializable { private static final long serialVersionUID = 187648346954430294L; private List<Integer> list1 = new CopyOnWriteArrayList<>(); private List<Integer> list2 = new CopyOnWriteArrayList<>(); public List<Integer> getList1() { return list1; } public List<Integer> getList2() { return list2; } }
这个问题可把我给坑坏了, 现在已经将此问题提交至 github, Issue地址
解决方案有3种
1. 避免使用在RPC调用或返回时使用 CopyOnWriteArrayList 对象
2. 避免使用 dubbo serialization, 改用 hessian 序列化
3. 将dubbo版本升级为 2.6.x, 并使用默认序列化(hessian)