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;

Reply via email to