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]