Fix hessian2 serialized short, byte is converted to int bug(#20)
fixes #19
diff --git a/pom.xml b/pom.xml
index cbee5eb..208810e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
<groupId>com.alibaba</groupId>
<artifactId>hessian-lite</artifactId>
<packaging>jar</packaging>
- <version>3.2.5-SNAPSHOT</version>
+ <version>3.2.7-SNAPSHOT</version>
<name>Hessian Lite(Alibaba embed version)</name>
<properties>
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..f241d63 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':
@@ -3360,8 +3366,9 @@
case 'N':
return null;
- case 'B':
- case 'b':
+ case BC_BINARY:
+ case BC_BINARY_CHUNK:
+ case 'b': //maybe it's a mistype of BC_BINARY_CHUNK
_isLastChunk = tag == 'B';
_chunkLength = (read() << 8) + read();
break;
@@ -3385,7 +3392,10 @@
_isLastChunk = true;
_chunkLength = tag - 0x20;
break;
-
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ _isLastChunk = true;
+ _chunkLength = (tag - 0x34) * 256 + read();
+ break;
default:
throw expect("binary", tag);
}
@@ -3408,13 +3418,14 @@
int code = read();
switch (code) {
- case 'b':
+ case BC_BINARY_CHUNK:
+ case 'b': //maybe it's a mistype of BC_BINARY_CHUNK
_isLastChunk = false;
_chunkLength = (read() << 8) + read();
break;
- case 'B':
+ case BC_BINARY:
_isLastChunk = true;
_chunkLength = (read() << 8) + read();
@@ -3439,7 +3450,10 @@
_isLastChunk = true;
_chunkLength = code - 0x20;
break;
-
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ _isLastChunk = true;
+ _chunkLength = (code - 0x34) * 256 + read();
+ break;
default:
throw expect("byte[]", code);
}
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/main/java/com/alibaba/com/caucho/hessian/io/SerializerFactory.java b/src/main/java/com/alibaba/com/caucho/hessian/io/SerializerFactory.java
index 8ac5fde..20c4187 100644
--- a/src/main/java/com/alibaba/com/caucho/hessian/io/SerializerFactory.java
+++ b/src/main/java/com/alibaba/com/caucho/hessian/io/SerializerFactory.java
@@ -80,6 +80,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -94,7 +95,7 @@
private static Deserializer OBJECT_DESERIALIZER
= new BasicDeserializer(BasicDeserializer.OBJECT);
-
+ private static ConcurrentHashMap _unrecognizedTypeCache = new ConcurrentHashMap();
private static HashMap _staticSerializerMap;
private static HashMap _staticDeserializerMap;
private static HashMap _staticTypeMap;
@@ -647,7 +648,7 @@
deserializer = new ArrayDeserializer(subDeserializer.getType());
else
deserializer = new ArrayDeserializer(Object.class);
- } else {
+ } else if (_unrecognizedTypeCache.get(type) == null) {
try {
Class cl = Class.forName(type, false, _loader);
deserializer = getDeserializer(cl);
@@ -655,7 +656,12 @@
log.warning("Hessian/Burlap: '" + type + "' is an unknown class in " + _loader + ":\n" + e);
_typeNotFoundDeserializerMap.put(type, PRESENT);
log.log(Level.FINER, e.toString(), e);
+ _unrecognizedTypeCache.put(type, new AtomicLong(1L));
}
+ } else {
+ ((AtomicLong) _unrecognizedTypeCache.get(type)).incrementAndGet();
+ if (((AtomicLong) _unrecognizedTypeCache.get(type)).get() % 2000L == 0L)
+ ((AtomicLong) _unrecognizedTypeCache.get(type)).getAndSet(1L);
}
if (deserializer != null) {
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 abe66a9..5bb08a3 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;
}
}