修复hessian在集合类反序列化时,包装类为null返回基本类型默认值的bug: https://github.com/apache/incubator-dubbo/issues/3640
diff --git a/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianInput.java b/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianInput.java
index 1d63fec..db0e574 100644
--- a/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianInput.java
+++ b/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianInput.java
@@ -100,6 +100,8 @@
public void setSerializerFactory(SerializerFactory ser) {
}
+ public abstract boolean checkAndReadNull();
+
/**
* Reads the call
* <p>
diff --git a/src/main/java/com/alibaba/com/caucho/hessian/io/BasicDeserializer.java b/src/main/java/com/alibaba/com/caucho/hessian/io/BasicDeserializer.java
index 20c593f..dc631e5 100644
--- a/src/main/java/com/alibaba/com/caucho/hessian/io/BasicDeserializer.java
+++ b/src/main/java/com/alibaba/com/caucho/hessian/io/BasicDeserializer.java
@@ -148,6 +148,9 @@
@Override
public Object readObject(AbstractHessianInput in)
throws IOException {
+ if (in.checkAndReadNull()) {
+ return null;
+ }
switch (_code) {
case NULL:
// hessian/3490
diff --git a/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionDeserializer.java b/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionDeserializer.java
index 827f7a3..fb23606 100644
--- a/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionDeserializer.java
+++ b/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionDeserializer.java
@@ -92,7 +92,7 @@
}
while (!in.isEnd()) {
- deserializerList(in, deserializer, list);
+ list.add(deserializer != null ? deserializer.readObject(in) : in.readObject());
}
@@ -121,23 +121,13 @@
}
for (; length > 0; length--) {
- deserializerList(in, deserializer, list);
+ list.add(deserializer != null ? deserializer.readObject(in) : in.readObject());
}
return list;
}
- private void deserializerList(AbstractHessianInput in, Deserializer deserializer, Collection list) throws IOException {
- Hessian2Input._isNull = false;
- Object object = deserializer != null ? deserializer.readObject(in) : in.readObject();
- if (Hessian2Input._isNull) {
- list.add(null);
- } else {
- list.add(object);
- }
- }
-
private Collection createList()
throws IOException {
Collection list = null;
diff --git a/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Input.java b/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Input.java
index 3d1f731..9cdef6a 100644
--- a/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Input.java
+++ b/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Input.java
@@ -90,7 +90,6 @@
private static final int GAP = 16;
private static Field _detailMessageField;
private static boolean _isCloseStreamOnClose;
- public static boolean _isNull = false;
static {
try {
@@ -185,6 +184,19 @@
return _replyFault;
}
+ @Override
+ public boolean checkAndReadNull() {
+ try {
+ int tag = read();
+ if ('N' == tag) {
+ return true;
+ }
+ _offset--;
+ } catch (IOException ignored) {
+ }
+ return false;
+ }
+
/**
* Starts reading the call
* <p>
@@ -752,12 +764,10 @@
public final int readInt()
throws IOException {
//int tag = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
- _isNull = false;
int tag = read();
switch (tag) {
case 'N':
- _isNull = true;
return 0;
case 'F':
@@ -973,12 +983,10 @@
@Override
public long readLong()
throws IOException {
- _isNull = false;
int tag = read();
switch (tag) {
case 'N':
- _isNull = true;
return 0;
case 'F':
@@ -1203,12 +1211,10 @@
@Override
public double readDouble()
throws IOException {
- _isNull = false;
int tag = read();
switch (tag) {
case 'N':
- _isNull = true;
return 0;
case 'F':
diff --git a/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInput.java b/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInput.java
index ffc1732..14b3096 100644
--- a/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInput.java
+++ b/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInput.java
@@ -170,6 +170,11 @@
return _replyFault;
}
+ @Override
+ public boolean checkAndReadNull() {
+ return _peek == 'N';
+ }
+
/**
* Starts reading the call
* <p>
diff --git a/src/test/java/com/alibaba/com/caucho/hessian/io/CollectionSerializerTest.java b/src/test/java/com/alibaba/com/caucho/hessian/io/CollectionSerializerTest.java
index 0b20240..75aa608 100644
--- a/src/test/java/com/alibaba/com/caucho/hessian/io/CollectionSerializerTest.java
+++ b/src/test/java/com/alibaba/com/caucho/hessian/io/CollectionSerializerTest.java
@@ -17,15 +17,18 @@
package com.alibaba.com.caucho.hessian.io;
import com.alibaba.com.caucho.hessian.io.base.SerializeTestBase;
-
-import org.junit.Assert;
-import org.junit.Test;
-
+import com.alibaba.com.caucho.hessian.io.beans.SubUser;
+import java.io.IOException;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Vector;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.junit.Assert;
+import org.junit.Test;
public class CollectionSerializerTest extends SerializeTestBase {
@Test
@@ -40,6 +43,46 @@
}
@Test
+ public void testSubUser() throws IOException {
+ int times = 100;
+ final CountDownLatch latch = new CountDownLatch(times);
+ final AtomicInteger error = new AtomicInteger();
+ for (int i = 0; i < times; i++) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ for (int j = 0; j < 100; j++) {
+ try {
+ SubUser subUser = new SubUser();
+ subUser.setUserId(1);
+ subUser.setUserName("tony");
+ List<Integer> list1 = Arrays.asList(null, 3, 1);
+ List<Double> list2 = Arrays.asList(null, 1.1, 1.2);
+ List<Boolean> list3 = Arrays.asList(false, null, true);
+ subUser.setAgeList(list1);
+ subUser.setWeightList(list2);
+ subUser.setSexyList(list3);
+ SubUser serializeUser = baseHessian2Serialize(subUser);
+ Assert.assertEquals(subUser.getAgeList(), serializeUser.getAgeList());
+ Assert.assertEquals(subUser.getWeightList(), serializeUser.getWeightList());
+ Assert.assertEquals(subUser.getSexyList(), serializeUser.getSexyList());
+ } catch (Throwable e) {
+ error.incrementAndGet();
+ }
+ }
+ latch.countDown();
+ }
+ }).start();
+ }
+ try {
+ latch.await();
+ Assert.assertEquals(0, error.get());
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
public void testListSerializer() throws Exception {
List<Integer> list = new LinkedList<>();
diff --git a/src/test/java/com/alibaba/com/caucho/hessian/io/HessianJavaSerializeTest.java b/src/test/java/com/alibaba/com/caucho/hessian/io/HessianJavaSerializeTest.java
index d9b46c8..8aa7ac6 100644
--- a/src/test/java/com/alibaba/com/caucho/hessian/io/HessianJavaSerializeTest.java
+++ b/src/test/java/com/alibaba/com/caucho/hessian/io/HessianJavaSerializeTest.java
@@ -66,10 +66,10 @@
list.add(null);
list.add(null);
list.add(3);
- subUser.setWage(list);
+ subUser.setAgeList(list);
SubUser serializedUser = baseHessian2Serialize(subUser);
- Assert.assertEquals(subUser.getWage(), serializedUser.getWage());
+ Assert.assertEquals(subUser.getAgeList(), serializedUser.getAgeList());
}
diff --git a/src/test/java/com/alibaba/com/caucho/hessian/io/beans/SubUser.java b/src/test/java/com/alibaba/com/caucho/hessian/io/beans/SubUser.java
index 5f988cf..7553f48 100644
--- a/src/test/java/com/alibaba/com/caucho/hessian/io/beans/SubUser.java
+++ b/src/test/java/com/alibaba/com/caucho/hessian/io/beans/SubUser.java
@@ -25,7 +25,9 @@
public class SubUser extends BaseUser implements Serializable {
private static final long serialVersionUID = 4017613093053853415L;
private String userName;
- private List<Integer> wage;
+ private List<Integer> ageList;
+ private List<Double> weightList;
+ private List<Boolean> sexyList;
@Override
public String getUserName() {
@@ -37,11 +39,27 @@
this.userName = userName;
}
- public List<Integer> getWage() {
- return wage;
+ public List<Integer> getAgeList() {
+ return ageList;
}
- public void setWage(List<Integer> wage) {
- this.wage = wage;
+ public void setAgeList(List<Integer> ageList) {
+ this.ageList = ageList;
+ }
+
+ public List<Double> getWeightList() {
+ return weightList;
+ }
+
+ public void setWeightList(List<Double> weightList) {
+ this.weightList = weightList;
+ }
+
+ public List<Boolean> getSexyList() {
+ return sexyList;
+ }
+
+ public void setSexyList(List<Boolean> sexyList) {
+ this.sexyList = sexyList;
}
}