This is an automated email from the ASF dual-hosted git repository.
zrlw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-hessian-lite.git
The following commit(s) were added to refs/heads/master by this push:
new c5ae890b Fixed addRef execution timing issue (#93)
c5ae890b is described below
commit c5ae890b749d344402e9f3edb5bc79c3a8a1111e
Author: zrlw <[email protected]>
AuthorDate: Thu Sep 18 11:26:39 2025 +0800
Fixed addRef execution timing issue (#93)
---
.../com/caucho/hessian/io/AbstractSerializer.java | 15 +-
.../com/caucho/hessian/io/Hessian2Output.java | 35 +---
.../hessian/io/java8/Java8TimeSerializerTest.java | 215 +++++++++++++++++++--
.../Java8TimeSerializerUseCompactModeTest.java | 4 +
4 files changed, 217 insertions(+), 52 deletions(-)
diff --git
a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractSerializer.java
b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractSerializer.java
index 199d17a6..456dbc14 100644
---
a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractSerializer.java
+++
b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractSerializer.java
@@ -65,20 +65,18 @@ abstract public class AbstractSerializer implements
Serializer {
@Override
public void writeObject(Object obj, AbstractHessianOutput out)
throws IOException {
- if (out.addRef(obj)) {
+ int ref = out.getRef(obj);
+ if (ref >= 0) {
+ // shared mode is true if the result of getRef is not less than
zero.
+ out.writeRef(ref);
return;
}
try {
Object replace = writeReplace(obj);
-
if (replace != null) {
- // out.removeRef(obj);
-
out.writeObject(replace);
-
out.replaceRef(replace, obj);
-
return;
}
} catch (RuntimeException e) {
@@ -88,9 +86,12 @@ abstract public class AbstractSerializer implements
Serializer {
throw new HessianException(e);
}
+ // add reference if writeReplace returns null and shared mode is true.
+ out.addRef(obj);
+
Class<?> cl = getClass(obj);
- int ref = out.writeObjectBegin(cl.getName());
+ ref = out.writeObjectBegin(cl.getName());
if (ref < -1) {
writeObject10(obj, out);
diff --git
a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Output.java
b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Output.java
index ed83316b..8be09d41 100644
---
a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Output.java
+++
b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Output.java
@@ -88,7 +88,6 @@ public class Hessian2Output
private final byte[] _buffer = new byte[SIZE];
// the output stream/
protected OutputStream _os;
- private int _refCount = 0;
private boolean _isCloseStreamOnClose;
// map of types
private HashMap<String, Integer> _typeRefs;
@@ -99,10 +98,8 @@ public class Hessian2Output
private boolean _isUnshared;
/**
- * Creates a new Hessian output stream, initialized with an
- * underlying output stream.
- *
- * @param os the underlying output stream.
+ * Creates a new Hessian output stream instance without initializing it
+ * with an underlying output stream. The output stream must be set before
use.
*/
public Hessian2Output() {
}
@@ -210,8 +207,6 @@ public class Hessian2Output
* <code><pre>
* C
* </pre></code>
- *
- * @param method the method name to call.
*/
@Override
public void startCall()
@@ -402,7 +397,7 @@ public class Hessian2Output
_buffer[_offset++] = (byte) 'F';
_buffer[_offset++] = (byte) 'H';
- addRef(new Object(), _refCount++, false);
+ addRef(new Object(), _refs.size(), false);
writeString("code");
writeString(code);
@@ -867,8 +862,6 @@ public class Hessian2Output
* <code><pre>
* N
* </pre></code>
- *
- * @param value the string value to write.
*/
public void writeNull()
throws IOException {
@@ -984,8 +977,6 @@ public class Hessian2Output
* <code><pre>
* N
* </pre></code>
- *
- * @param value the string value to write.
*/
public void writeString(char[] buffer, int offset, int length)
throws IOException {
@@ -1048,8 +1039,6 @@ public class Hessian2Output
* <code><pre>
* N
* </pre></code>
- *
- * @param value the string value to write.
*/
public void writeBytes(byte[] buffer)
throws IOException {
@@ -1075,8 +1064,6 @@ public class Hessian2Output
* <code><pre>
* N
* </pre></code>
- *
- * @param value the string value to write.
*/
public void writeBytes(byte[] buffer, int offset, int length)
throws IOException {
@@ -1248,21 +1235,17 @@ public class Hessian2Output
public boolean addRef(Object object)
throws IOException {
if (_isUnshared) {
- _refCount++;
return false;
}
- int newRef = _refCount;
+ int newRef = _refs.size();
int ref = addRef(object, newRef, false);
if (ref != newRef) {
writeRef(ref);
-
return true;
} else {
- _refCount++;
-
return false;
}
}
@@ -1302,15 +1285,12 @@ public class Hessian2Output
}
int value = _refs.get(oldRef);
-
if (value >= 0) {
addRef(newRef, value, true);
-
_refs.remove(oldRef);
-
return true;
- } else
- return false;
+ }
+ return false;
}
private int addRef(Object value, int newRef, boolean isReplace) {
@@ -1348,7 +1328,6 @@ public class Hessian2Output
throws IOException {
if (_refs != null) {
_refs.clear();
- _refCount = 0;
}
flushBuffer();
@@ -1569,7 +1548,6 @@ public class Hessian2Output
public void resetReferences() {
if (_refs != null) {
_refs.clear();
- _refCount = 0;
}
}
@@ -1579,7 +1557,6 @@ public class Hessian2Output
public void reset() {
if (_refs != null) {
_refs.clear();
- _refCount = 0;
}
_classRefs.clear();
diff --git
a/java-8-test/src/test/java/com/alibaba/com/caucho/hessian/io/java8/Java8TimeSerializerTest.java
b/java-8-test/src/test/java/com/alibaba/com/caucho/hessian/io/java8/Java8TimeSerializerTest.java
index 9a743505..12e07091 100644
---
a/java-8-test/src/test/java/com/alibaba/com/caucho/hessian/io/java8/Java8TimeSerializerTest.java
+++
b/java-8-test/src/test/java/com/alibaba/com/caucho/hessian/io/java8/Java8TimeSerializerTest.java
@@ -22,6 +22,7 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.IOException;
+import java.io.Serializable;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
@@ -42,7 +43,10 @@ import java.time.chrono.HijrahDate;
import java.time.chrono.JapaneseDate;
import java.time.chrono.MinguoDate;
import java.time.chrono.ThaiBuddhistDate;
+import java.util.ArrayList;
import java.util.Calendar;
+import java.util.List;
+import java.util.Objects;
/**
* Test Java8TimeSerializer class
@@ -56,78 +60,212 @@ public class Java8TimeSerializerTest extends
SerializeTestBase {
@Test
public void testInstant() throws Exception {
- testJava8Time(Instant.now());
+ List<Object> list = new ArrayList<>();
+ Instant instant = Instant.now();
+ list.add(instant);
+ list.add(instant);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(instant);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testDuration() throws Exception {
- testJava8Time(Duration.ofDays(2));
+ List<Object> list = new ArrayList<>();
+ Duration duration = Duration.ofDays(2);
+ list.add(duration);
+ list.add(duration);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(duration);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testLocalDate() throws Exception {
- testJava8Time(LocalDate.now());
+ List<Object> list = new ArrayList<>();
+ LocalDate localDate = LocalDate.now();
+ list.add(localDate);
+ list.add(localDate);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(localDate);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testLocalDateTime() throws Exception {
- testJava8Time(LocalDateTime.now());
+ List<Object> list = new ArrayList<>();
+ LocalDateTime localDateTime = LocalDateTime.now();
+ list.add(localDateTime);
+ list.add(localDateTime);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(localDateTime);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testLocalTime() throws Exception {
- testJava8Time(LocalTime.now());
+ List<Object> list = new ArrayList<>();
+ LocalTime localTime = LocalTime.now();
+ list.add(localTime);
+ list.add(localTime);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(localTime);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testYear() throws Exception {
- testJava8Time(Year.now());
+ List<Object> list = new ArrayList<>();
+ Year year = Year.now();
+ list.add(year);
+ list.add(year);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(year);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testYearMonth() throws Exception {
- testJava8Time(YearMonth.now());
+ List<Object> list = new ArrayList<>();
+ YearMonth yearMonth = YearMonth.now();
+ list.add(yearMonth);
+ list.add(yearMonth);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(yearMonth);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testMonthDay() throws Exception {
- testJava8Time(MonthDay.now());
+ List<Object> list = new ArrayList<>();
+ MonthDay monthDay = MonthDay.now();
+ list.add(monthDay);
+ list.add(monthDay);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(monthDay);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testPeriod() throws Exception {
- testJava8Time(Period.ofDays(3));
+ List<Object> list = new ArrayList<>();
+ Period period = Period.ofDays(3);
+ list.add(period);
+ list.add(period);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(period);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testOffsetTime() throws Exception {
- testJava8Time(OffsetTime.now());
+ List<Object> list = new ArrayList<>();
+ OffsetTime offsetTime = OffsetTime.now();
+ list.add(offsetTime);
+ list.add(offsetTime);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(offsetTime);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testZoneOffset() throws Exception {
- testJava8Time(ZoneOffset.ofHours( 8));
+ List<Object> list = new ArrayList<>();
+ ZoneOffset zoneOffset = ZoneOffset.ofHours(8);
+ list.add(zoneOffset);
+ list.add(zoneOffset);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(zoneOffset);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testOffsetDateTime() throws Throwable {
- testJava8Time(OffsetDateTime.now());
+ List<Object> list = new ArrayList<>();
+ OffsetDateTime offsetDateTime = OffsetDateTime.now();
+ list.add(offsetDateTime);
+ list.add(offsetDateTime);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(offsetDateTime);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testZonedDateTime() throws Exception {
- testJava8Time(ZonedDateTime.now());
+ List<Object> list = new ArrayList<>();
+ ZonedDateTime zonedDateTime = ZonedDateTime.now();
+ list.add(zonedDateTime);
+ list.add(zonedDateTime);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(zonedDateTime);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testZoneId() throws Exception {
- testJava8Time(ZoneId.of( "America/New_York"));
+ List<Object> list = new ArrayList<>();
+ ZoneId zoneId = ZoneId.of("America/New_York");
+ list.add(zoneId);
+ list.add(zoneId);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(zoneId);
+ list.add(o);
+ testJava8Time(list);
}
@Test
public void testCalendar() throws IOException {
+ List<Object> list = new ArrayList<>();
Calendar calendar = Calendar.getInstance();
- testJava8Time(calendar);
+ list.add(calendar);
+ list.add(calendar);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(calendar);
+ list.add(o);
+ testJava8Time(list);
}
@Test
@@ -152,8 +290,27 @@ public class Java8TimeSerializerTest extends
SerializeTestBase {
testJava8Time(ChronoPeriod.between(ThaiBuddhistDate.now(),
ThaiBuddhistDate.now()));
}
+
+ @Test
+ void testChronologyList() throws IOException {
+ List<Object> list = new ArrayList<>();
+ Chronology chronology = Chronology.of("islamic");
+ list.add(chronology);
+ list.add(chronology);
+ TestInner o = new TestInner();
+ list.add(o);
+ list.add(o);
+ list.add(chronology);
+ list.add(o);
+ testJava8Time(list);
+ }
+
protected void testJava8Time(Object expected) throws IOException {
- Assertions.assertEquals(expected, baseHessian2Serialize(expected));
+ Object result = baseHessian2Serialize(expected);
+ Assertions.assertEquals(expected, result);
+ if (expected instanceof List && !((List) expected).isEmpty() &&
((List) expected).get(0) instanceof Chronology) {
+ return;
+ }
if (expected instanceof Chronology || expected instanceof ChronoPeriod
|| expected instanceof JapaneseDate
|| expected instanceof HijrahDate || expected instanceof
MinguoDate || expected instanceof ThaiBuddhistDate) {
return;
@@ -162,4 +319,30 @@ public class Java8TimeSerializerTest extends
SerializeTestBase {
Assertions.assertEquals(expected, hessian4ToHessian3(expected));
Assertions.assertEquals(expected, hessian3ToHessian4(expected));
}
+
+ /**
+ * Helper class used in tests to verify reference handling during
serialization.
+ * Instances of this class are added multiple times to collections to
ensure
+ * that object references are correctly preserved or duplicated as expected
+ * when serializing and deserializing with Hessian.
+ */
+ static class TestInner implements Serializable {
+ String value;
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (o instanceof TestInner) {
+ return Objects.equals(((TestInner) o).value, value);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(value);
+ }
+ }
}
diff --git
a/java-8-test/src/test/java/com/alibaba/com/caucho/hessian/io/java8/Java8TimeSerializerUseCompactModeTest.java
b/java-8-test/src/test/java/com/alibaba/com/caucho/hessian/io/java8/Java8TimeSerializerUseCompactModeTest.java
index 333086f9..e54acdd9 100644
---
a/java-8-test/src/test/java/com/alibaba/com/caucho/hessian/io/java8/Java8TimeSerializerUseCompactModeTest.java
+++
b/java-8-test/src/test/java/com/alibaba/com/caucho/hessian/io/java8/Java8TimeSerializerUseCompactModeTest.java
@@ -29,6 +29,7 @@ import java.time.chrono.HijrahDate;
import java.time.chrono.JapaneseDate;
import java.time.chrono.MinguoDate;
import java.time.chrono.ThaiBuddhistDate;
+import java.util.List;
/**
* Test Java8TimeSerializer class use compact mode
@@ -52,6 +53,9 @@ public class Java8TimeSerializerUseCompactModeTest extends
Java8TimeSerializerTe
protected void testJava8Time(Object expected) throws IOException {
Assertions.assertEquals(expected, baseHessian2Serialize(expected));
+ if (expected instanceof List && !((List) expected).isEmpty() &&
((List) expected).get(0) instanceof Chronology) {
+ return;
+ }
if (expected instanceof Chronology || expected instanceof ChronoPeriod
|| expected instanceof JapaneseDate
|| expected instanceof HijrahDate || expected instanceof
MinguoDate || expected instanceof ThaiBuddhistDate) {
return;