fix hessian2 deserializer bug #3640 (#8)

* fix hessian2 deserializer bug #3640
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 1347aa6..827f7a3 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
@@ -91,8 +91,10 @@
             deserializer = factory.getDeserializer(expectType.getName());
         }
 
-        while (!in.isEnd())
-            list.add(deserializer != null ? deserializer.readObject(in) : in.readObject());
+        while (!in.isEnd()) {
+            deserializerList(in, deserializer, list);
+        }
+
 
         in.readEnd();
 
@@ -118,12 +120,24 @@
             deserializer = factory.getDeserializer(expectType.getName());
         }
 
-        for (; length > 0; length--)
-            list.add(deserializer != null ? deserializer.readObject(in) : in.readObject());
+        for (; length > 0; length--) {
+            deserializerList(in, deserializer, list);
+        }
+
 
         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 8d6d7d7..3d1f731 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,6 +90,7 @@
     private static final int GAP = 16;
     private static Field _detailMessageField;
     private static boolean _isCloseStreamOnClose;
+    public static boolean _isNull = false;
 
     static {
         try {
@@ -751,10 +752,12 @@
     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':
@@ -833,7 +836,7 @@
             case 0xbf:
                 return tag - BC_INT_ZERO;
 
-      /* byte int */
+            /* byte int */
             case 0xc0:
             case 0xc1:
             case 0xc2:
@@ -852,7 +855,7 @@
             case 0xcf:
                 return ((tag - BC_INT_BYTE_ZERO) << 8) + read();
 
-      /* short int */
+            /* short int */
             case 0xd0:
             case 0xd1:
             case 0xd2:
@@ -898,7 +901,7 @@
             case 0xef:
                 return tag - BC_LONG_ZERO;
 
-      /* byte long */
+            /* byte long */
             case 0xf0:
             case 0xf1:
             case 0xf2:
@@ -917,7 +920,7 @@
             case 0xff:
                 return ((tag - BC_LONG_BYTE_ZERO) << 8) + read();
 
-      /* short long */
+            /* short long */
             case 0x38:
             case 0x39:
             case 0x3a:
@@ -970,10 +973,12 @@
     @Override
     public long readLong()
             throws IOException {
+        _isNull = false;
         int tag = read();
 
         switch (tag) {
             case 'N':
+                _isNull = true;
                 return 0;
 
             case 'F':
@@ -1052,7 +1057,7 @@
             case 0xbf:
                 return tag - BC_INT_ZERO;
 
-      /* byte int */
+            /* byte int */
             case 0xc0:
             case 0xc1:
             case 0xc2:
@@ -1071,7 +1076,7 @@
             case 0xcf:
                 return ((tag - BC_INT_BYTE_ZERO) << 8) + read();
 
-      /* short int */
+            /* short int */
             case 0xd0:
             case 0xd1:
             case 0xd2:
@@ -1123,7 +1128,7 @@
             case 0xef:
                 return tag - BC_LONG_ZERO;
 
-      /* byte long */
+            /* byte long */
             case 0xf0:
             case 0xf1:
             case 0xf2:
@@ -1142,7 +1147,7 @@
             case 0xff:
                 return ((tag - BC_LONG_BYTE_ZERO) << 8) + read();
 
-      /* short long */
+            /* short long */
             case 0x38:
             case 0x39:
             case 0x3a:
@@ -1198,10 +1203,12 @@
     @Override
     public double readDouble()
             throws IOException {
+        _isNull = false;
         int tag = read();
 
         switch (tag) {
             case 'N':
+                _isNull = true;
                 return 0;
 
             case 'F':
@@ -1280,7 +1287,7 @@
             case 0xbf:
                 return tag - 0x90;
 
-      /* byte int */
+            /* byte int */
             case 0xc0:
             case 0xc1:
             case 0xc2:
@@ -1299,7 +1306,7 @@
             case 0xcf:
                 return ((tag - BC_INT_BYTE_ZERO) << 8) + read();
 
-      /* short int */
+            /* short int */
             case 0xd0:
             case 0xd1:
             case 0xd2:
@@ -1342,7 +1349,7 @@
             case 0xef:
                 return tag - BC_LONG_ZERO;
 
-      /* byte long */
+            /* byte long */
             case 0xf0:
             case 0xf1:
             case 0xf2:
@@ -1361,7 +1368,7 @@
             case 0xff:
                 return ((tag - BC_LONG_BYTE_ZERO) << 8) + read();
 
-      /* short long */
+            /* short long */
             case 0x38:
             case 0x39:
             case 0x3a:
@@ -1437,7 +1444,6 @@
             _chunkLength = 0;
             return -1;
         }
-
         int tag = read();
 
         switch (tag) {
@@ -1658,7 +1664,7 @@
             case 0xbf:
                 return String.valueOf((tag - 0x90));
 
-      /* byte int */
+            /* byte int */
             case 0xc0:
             case 0xc1:
             case 0xc2:
@@ -1677,7 +1683,7 @@
             case 0xcf:
                 return String.valueOf(((tag - BC_INT_BYTE_ZERO) << 8) + read());
 
-      /* short int */
+            /* short int */
             case 0xd0:
             case 0xd1:
             case 0xd2:
@@ -1721,7 +1727,7 @@
             case 0xef:
                 return String.valueOf(tag - BC_LONG_ZERO);
 
-      /* byte long */
+            /* byte long */
             case 0xf0:
             case 0xf1:
             case 0xf2:
@@ -1740,7 +1746,7 @@
             case 0xff:
                 return String.valueOf(((tag - BC_LONG_BYTE_ZERO) << 8) + read());
 
-      /* short long */
+            /* short long */
             case 0x38:
             case 0x39:
             case 0x3a:
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 3a50709..d9b46c8 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
@@ -24,10 +24,12 @@
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * fix hessian serialize bug:
  * the filed of parent class will cover the filed of sub class
- *
  */
 public class HessianJavaSerializeTest extends SerializeTestBase {
 
@@ -54,6 +56,23 @@
 
     }
 
+
+    @Test
+    public void testSubUserWage() throws Exception {
+        SubUser subUser = new SubUser();
+        subUser.setUserId(1);
+        subUser.setUserName("tom");
+        List<Integer> list = new ArrayList<>();
+        list.add(null);
+        list.add(null);
+        list.add(3);
+        subUser.setWage(list);
+
+        SubUser serializedUser = baseHessian2Serialize(subUser);
+        Assert.assertEquals(subUser.getWage(), serializedUser.getWage());
+
+    }
+
     @Test
     public void testGetGrandsonUserName() throws Exception {
         GrandsonUser grandsonUser = new GrandsonUser();
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 3c7214f..5f988cf 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
@@ -17,19 +17,31 @@
 package com.alibaba.com.caucho.hessian.io.beans;
 
 import java.io.Serializable;
+import java.util.List;
 
 /**
+ *
  */
 public class SubUser extends BaseUser implements Serializable {
     private static final long serialVersionUID = 4017613093053853415L;
     private String userName;
+    private List<Integer> wage;
 
     @Override
     public String getUserName() {
         return userName;
     }
+
     @Override
     public void setUserName(String userName) {
         this.userName = userName;
     }
+
+    public List<Integer> getWage() {
+        return wage;
+    }
+
+    public void setWage(List<Integer> wage) {
+        this.wage = wage;
+    }
 }