This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 40646a4f4 feat(java): build Descriptors with final ref_tracking flags 
(#3070)
40646a4f4 is described below

commit 40646a4f4dd8a23d4d641374c7b9e97aec4a24b5
Author: Shawn Yang <[email protected]>
AuthorDate: Fri Dec 26 15:12:03 2025 +0800

    feat(java): build Descriptors with final ref_tracking flags (#3070)
    
    ## Why?
    
    
    
    ## What does this PR do?
    
    
    
    ## Related issues
    
    
    
    ## Does this PR introduce any user-facing change?
    
    
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
---
 .../fory/builder/BaseObjectCodecBuilder.java       | 19 +++-------
 .../main/java/org/apache/fory/meta/ClassDef.java   | 44 ++--------------------
 .../org/apache/fory/resolver/ClassResolver.java    | 20 ++++++----
 .../fory/serializer/AbstractObjectSerializer.java  |  5 +--
 4 files changed, 23 insertions(+), 65 deletions(-)

diff --git 
a/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
 
b/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
index e1be80dc8..0ad81d45e 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/builder/BaseObjectCodecBuilder.java
@@ -404,13 +404,8 @@ public abstract class BaseObjectCodecBuilder extends 
CodecBuilder {
       Expression fieldValue, Expression buffer, Descriptor descriptor) {
     TypeRef<?> typeRef = descriptor.getTypeRef();
     boolean nullable = descriptor.isNullable();
-
-    boolean useRefTracking;
-    if (needWriteRef(typeRef)) {
-      useRefTracking = descriptor.isTrackingRef();
-    } else {
-      useRefTracking = false;
-    }
+    // descriptor.isTrackingRef() already includes the needWriteRef check
+    boolean useRefTracking = descriptor.isTrackingRef();
 
     if (useRefTracking) {
       return new If(
@@ -1774,14 +1769,10 @@ public abstract class BaseObjectCodecBuilder extends 
CodecBuilder {
       Expression buffer, Descriptor descriptor, Function<Expression, 
Expression> callback) {
     TypeRef<?> typeRef = descriptor.getTypeRef();
     boolean nullable = descriptor.isNullable();
-
+    // descriptor.isTrackingRef() already includes the needWriteRef check
+    boolean useRefTracking = descriptor.isTrackingRef();
+    // Check if type normally needs ref (for preserveRefId when ref tracking 
is disabled)
     boolean typeNeedsRef = needWriteRef(typeRef);
-    boolean useRefTracking;
-    if (needWriteRef(typeRef)) {
-      useRefTracking = descriptor.isTrackingRef();
-    } else {
-      useRefTracking = false;
-    }
 
     if (useRefTracking) {
       return readRef(buffer, callback, () -> 
deserializeForNotNullForField(buffer, typeRef, null));
diff --git a/java/fory-core/src/main/java/org/apache/fory/meta/ClassDef.java 
b/java/fory-core/src/main/java/org/apache/fory/meta/ClassDef.java
index 99c70efeb..707af1e40 100644
--- a/java/fory-core/src/main/java/org/apache/fory/meta/ClassDef.java
+++ b/java/fory-core/src/main/java/org/apache/fory/meta/ClassDef.java
@@ -29,7 +29,6 @@ import java.io.ObjectStreamClass;
 import java.io.Serializable;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
-import java.lang.reflect.Member;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -39,8 +38,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.SortedMap;
-import java.util.TreeMap;
 import java.util.stream.Collectors;
 import org.apache.fory.Fory;
 import org.apache.fory.annotation.ForyField;
@@ -63,7 +60,6 @@ import org.apache.fory.serializer.NonexistentClass;
 import org.apache.fory.serializer.converter.FieldConverter;
 import org.apache.fory.serializer.converter.FieldConverters;
 import org.apache.fory.type.Descriptor;
-import org.apache.fory.type.DescriptorBuilder;
 import org.apache.fory.type.FinalObjectTypeStub;
 import org.apache.fory.type.GenericType;
 import org.apache.fory.type.TypeUtils;
@@ -349,43 +345,17 @@ public class ClassDef implements Serializable {
    */
   public List<Descriptor> getDescriptors(TypeResolver resolver, Class<?> cls) {
     if (descriptors == null) {
-      SortedMap<Member, Descriptor> allDescriptorsMap =
-          resolver.getFory().getClassResolver().getAllDescriptorsMap(cls, 
true);
+      // getFieldDescriptors already handles ref tracking computation and 
cache update
+      Collection<Descriptor> fieldDescriptors = 
resolver.getFieldDescriptors(cls, true);
       Map<String, Descriptor> descriptorsMap = new HashMap<>();
       Map<Short, Descriptor> fieldIdToDescriptorMap = new HashMap<>();
-      Map<Member, Descriptor>[] newDescriptors = new Map[] {null};
 
-      for (Map.Entry<Member, Descriptor> e : allDescriptorsMap.entrySet()) {
-        String fullName = e.getKey().getDeclaringClass().getName() + "." + 
e.getKey().getName();
-        Descriptor desc = e.getValue();
+      for (Descriptor desc : fieldDescriptors) {
+        String fullName = desc.getDeclaringClass() + "." + desc.getName();
         if (descriptorsMap.put(fullName, desc) != null) {
           throw new IllegalStateException("Duplicate key");
         }
 
-        if (e.getKey() instanceof Field) {
-          boolean refTracking = resolver.getFory().trackingRef();
-          ForyField foryField = desc.getForyField();
-          // update ref tracking if
-          // - global ref tracking is disabled but field is tracking ref 
(@ForyField#ref set)
-          // - global ref tracking is enabled but field is not tracking ref 
(@ForyField#ref not set)
-          boolean needsUpdate =
-              (refTracking && foryField == null && !desc.isTrackingRef())
-                  || (foryField != null && desc.isTrackingRef());
-
-          if (needsUpdate) {
-            if (newDescriptors[0] == null) {
-              newDescriptors[0] = new HashMap<>();
-            }
-            boolean newTrackingRef = refTracking && foryField == null;
-            Descriptor newDescriptor =
-                new 
DescriptorBuilder(desc).trackingRef(newTrackingRef).build();
-
-            descriptorsMap.put(fullName, newDescriptor);
-            desc = newDescriptor;
-            newDescriptors[0].put(e.getKey(), newDescriptor);
-          }
-        }
-
         // If the field has @ForyField annotation with field ID, index by 
field ID
         if (desc.getForyField() != null) {
           int fieldId = desc.getForyField().id();
@@ -404,12 +374,6 @@ public class ClassDef implements Serializable {
         }
       }
 
-      if (newDescriptors[0] != null) {
-        SortedMap<Member, Descriptor> allDescriptorsCopy = new 
TreeMap<>(allDescriptorsMap);
-        allDescriptorsCopy.putAll(newDescriptors[0]);
-        resolver.getFory().getClassResolver().updateDescriptorsCache(cls, 
true, allDescriptorsCopy);
-      }
-
       descriptors = new ArrayList<>(fieldsInfo.size());
       for (FieldInfo fieldInfo : fieldsInfo) {
         Descriptor descriptor;
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java 
b/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
index bc2c0276d..a65282cdc 100644
--- a/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
+++ b/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
@@ -1226,21 +1226,25 @@ public class ClassResolver extends TypeResolver {
             return;
           }
 
-          boolean shouldTrack = fory.trackingRef();
+          boolean globalRefTracking = fory.trackingRef();
           boolean hasForyField = descriptor.getForyField() != null;
-          // update ref tracking if
-          // - global ref tracking is enabled but field is not tracking ref 
(@ForyField#ref not set)
-          // - global ref tracking is disabled but field is tracking ref 
(@ForyField#ref set)
-          boolean needsUpdate =
-              (shouldTrack && !hasForyField)
-                  || (!shouldTrack && hasForyField && 
descriptor.isTrackingRef());
+          // Compute the final isTrackingRef value:
+          // 1. If global ref tracking is enabled and no @ForyField, use 
global setting
+          // 2. If @ForyField(ref=true) is set, use that (but can be 
overridden if global is off)
+          // 3. Additionally, check if the type actually supports ref tracking
+          boolean wantsRefTracking =
+              (globalRefTracking && !hasForyField)
+                  || (hasForyField && descriptor.isTrackingRef() && 
globalRefTracking);
+          // Compute the final tracking: type must support refs AND 
user/global wants tracking
+          boolean finalTrackingRef = wantsRefTracking && 
needToWriteRef(descriptor.getTypeRef());
+          boolean needsUpdate = finalTrackingRef != descriptor.isTrackingRef();
 
           if (needsUpdate) {
             if (newDescriptors[0] == null) {
               newDescriptors[0] = new HashMap<>();
             }
             Descriptor newDescriptor =
-                new 
DescriptorBuilder(descriptor).trackingRef(shouldTrack).build();
+                new 
DescriptorBuilder(descriptor).trackingRef(finalTrackingRef).build();
             result.add(newDescriptor);
             newDescriptors[0].put(member, newDescriptor);
           } else {
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/AbstractObjectSerializer.java
 
b/java/fory-core/src/main/java/org/apache/fory/serializer/AbstractObjectSerializer.java
index 8ff29fcb4..eedce3174 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/serializer/AbstractObjectSerializer.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/serializer/AbstractObjectSerializer.java
@@ -996,9 +996,8 @@ public abstract class AbstractObjectSerializer<T> extends 
Serializer<T> {
       this.fieldAccessor = d.getField() != null ? 
FieldAccessor.createAccessor(d.getField()) : null;
       fieldConverter = d.getFieldConverter();
       nullable = d.isNullable();
-      if (fory.trackingRef()) {
-        trackingRef = d.isTrackingRef();
-      }
+      // descriptor.isTrackingRef() already includes the needToWriteRef check
+      trackingRef = d.isTrackingRef();
     }
 
     @Override


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to