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/fury.git
The following commit(s) were added to refs/heads/main by this push:
new b2226602 fix(java): child container deep copy (#1911)
b2226602 is described below
commit b222660278d75e4ef0779d96667692d8c55de032
Author: zhaommmmomo <[email protected]>
AuthorDate: Sat Oct 26 23:32:57 2024 +0800
fix(java): child container deep copy (#1911)
## What does this PR do?
fix child container bug
<!-- Describe the purpose of this PR. -->
## Related issues
https://github.com/apache/fury/issues/1855
<!--
Is there any related issue? Please attach here.
- #xxxx0
- #xxxx1
- #xxxx2
-->
## Does this PR introduce any user-facing change?
<!--
If any user-facing interface changes, please [open an
issue](https://github.com/apache/fury/issues/new/choose) describing the
need to do so and update the document if necessary.
-->
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
<!--
When the PR has an impact on performance (if you don't know whether the
PR will have an impact on performance, you can submit the PR first, and
if it will have impact on performance, the code reviewer will explain
it), be sure to attach a benchmark data here.
-->
---
.../org/apache/fury/reflect/ReflectionUtils.java | 13 ++++
.../fury/serializer/AbstractObjectSerializer.java | 75 +++++++++++++++++++++-
.../collection/ChildContainerSerializers.java | 29 ++++++---
3 files changed, 106 insertions(+), 11 deletions(-)
diff --git
a/java/fury-core/src/main/java/org/apache/fury/reflect/ReflectionUtils.java
b/java/fury-core/src/main/java/org/apache/fury/reflect/ReflectionUtils.java
index 4654dc0c..f039e1fb 100644
--- a/java/fury-core/src/main/java/org/apache/fury/reflect/ReflectionUtils.java
+++ b/java/fury-core/src/main/java/org/apache/fury/reflect/ReflectionUtils.java
@@ -380,6 +380,19 @@ public class ReflectionUtils {
return fields;
}
+ public static List<Field> getFieldsWithoutSuperClasses(Class<?> cls,
Set<Class<?>> superClasses) {
+ Preconditions.checkNotNull(cls);
+ List<Field> fields = new ArrayList<>();
+ Class<?> clazz = cls;
+ do {
+ if (!superClasses.contains(clazz)) {
+ Collections.addAll(fields, clazz.getDeclaredFields());
+ }
+ clazz = clazz.getSuperclass();
+ } while (clazz != null);
+ return fields;
+ }
+
/** Get fields values from provided object. */
public static List<Object> getFieldValues(Collection<Field> fields, Object
o) {
List<Object> results = new ArrayList<>(fields.size());
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/AbstractObjectSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/AbstractObjectSerializer.java
index 2366c6ad..a6e3af86 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/AbstractObjectSerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/AbstractObjectSerializer.java
@@ -177,6 +177,56 @@ public abstract class AbstractObjectSerializer<T> extends
Serializer<T> {
}
}
+ public static void copyFields(
+ Fury fury, InternalFieldInfo[] fieldInfos, Object originObj, Object
newObj) {
+ for (InternalFieldInfo fieldInfo : fieldInfos) {
+ FieldAccessor fieldAccessor = fieldInfo.fieldAccessor;
+ long fieldOffset = fieldAccessor.getFieldOffset();
+ // record class won't go to this path;
+ assert fieldOffset != -1;
+ switch (fieldInfo.classId) {
+ case ClassResolver.PRIMITIVE_BYTE_CLASS_ID:
+ Platform.putByte(newObj, fieldOffset, Platform.getByte(originObj,
fieldOffset));
+ break;
+ case ClassResolver.PRIMITIVE_CHAR_CLASS_ID:
+ Platform.putChar(newObj, fieldOffset, Platform.getChar(originObj,
fieldOffset));
+ break;
+ case ClassResolver.PRIMITIVE_SHORT_CLASS_ID:
+ Platform.putShort(newObj, fieldOffset, Platform.getShort(originObj,
fieldOffset));
+ break;
+ case ClassResolver.PRIMITIVE_INT_CLASS_ID:
+ Platform.putInt(newObj, fieldOffset, Platform.getInt(originObj,
fieldOffset));
+ break;
+ case ClassResolver.PRIMITIVE_LONG_CLASS_ID:
+ Platform.putLong(newObj, fieldOffset, Platform.getLong(originObj,
fieldOffset));
+ break;
+ case ClassResolver.PRIMITIVE_FLOAT_CLASS_ID:
+ Platform.putFloat(newObj, fieldOffset, Platform.getFloat(originObj,
fieldOffset));
+ break;
+ case ClassResolver.PRIMITIVE_DOUBLE_CLASS_ID:
+ Platform.putDouble(newObj, fieldOffset,
Platform.getDouble(originObj, fieldOffset));
+ break;
+ case ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID:
+ Platform.putBoolean(newObj, fieldOffset,
Platform.getBoolean(originObj, fieldOffset));
+ break;
+ case ClassResolver.BOOLEAN_CLASS_ID:
+ case ClassResolver.BYTE_CLASS_ID:
+ case ClassResolver.CHAR_CLASS_ID:
+ case ClassResolver.SHORT_CLASS_ID:
+ case ClassResolver.INTEGER_CLASS_ID:
+ case ClassResolver.FLOAT_CLASS_ID:
+ case ClassResolver.LONG_CLASS_ID:
+ case ClassResolver.DOUBLE_CLASS_ID:
+ case ClassResolver.STRING_CLASS_ID:
+ Platform.putObject(newObj, fieldOffset,
Platform.getObject(originObj, fieldOffset));
+ break;
+ default:
+ Platform.putObject(
+ newObj, fieldOffset,
fury.copyObject(Platform.getObject(originObj, fieldOffset)));
+ }
+ }
+ }
+
private Object copyField(Object targetObject, long fieldOffset, short
classId) {
switch (classId) {
case ClassResolver.PRIMITIVE_BOOLEAN_CLASS_ID:
@@ -256,6 +306,29 @@ public abstract class AbstractObjectSerializer<T> extends
Serializer<T> {
return fieldInfos;
}
+ public static InternalFieldInfo[] buildFieldsInfo(Fury fury, List<Field>
fields) {
+ List<Descriptor> descriptors = new ArrayList<>();
+ for (Field field : fields) {
+ if (!Modifier.isTransient(field.getModifiers()) &&
!Modifier.isStatic(field.getModifiers())) {
+ descriptors.add(new Descriptor(field,
TypeRef.of(field.getGenericType()), null, null));
+ }
+ }
+ DescriptorGrouper descriptorGrouper =
+ createDescriptorGrouper(
+ fury.getClassResolver()::isMonomorphic,
+ descriptors,
+ false,
+ fury.compressInt(),
+ fury.compressLong());
+ Tuple3<Tuple2<FinalTypeField[], boolean[]>, GenericTypeField[],
GenericTypeField[]> infos =
+ buildFieldInfos(fury, descriptorGrouper);
+ InternalFieldInfo[] fieldInfos = new InternalFieldInfo[descriptors.size()];
+ System.arraycopy(infos.f0.f0, 0, fieldInfos, 0, infos.f0.f0.length);
+ System.arraycopy(infos.f1, 0, fieldInfos, infos.f0.f0.length,
infos.f1.length);
+ System.arraycopy(infos.f2, 0, fieldInfos, fieldInfos.length -
infos.f2.length, infos.f2.length);
+ return fieldInfos;
+ }
+
protected T newBean() {
if (constructor != null) {
try {
@@ -336,7 +409,7 @@ public abstract class AbstractObjectSerializer<T> extends
Serializer<T> {
fury);
}
- static class InternalFieldInfo {
+ public static class InternalFieldInfo {
protected final short classId;
protected final String qualifiedFieldName;
protected final FieldAccessor fieldAccessor;
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ChildContainerSerializers.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ChildContainerSerializers.java
index 57e76bb2..61acb790 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ChildContainerSerializers.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ChildContainerSerializers.java
@@ -21,6 +21,7 @@ package org.apache.fury.serializer.collection;
import static org.apache.fury.collection.Collections.ofHashSet;
+import java.lang.reflect.Field;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
@@ -40,6 +41,8 @@ import org.apache.fury.memory.MemoryBuffer;
import org.apache.fury.reflect.ReflectionUtils;
import org.apache.fury.resolver.ClassResolver;
import org.apache.fury.resolver.FieldResolver;
+import org.apache.fury.serializer.AbstractObjectSerializer;
+import org.apache.fury.serializer.AbstractObjectSerializer.InternalFieldInfo;
import org.apache.fury.serializer.CompatibleSerializer;
import org.apache.fury.serializer.JavaSerializer;
import org.apache.fury.serializer.ObjectSerializer;
@@ -127,7 +130,7 @@ public class ChildContainerSerializers {
ArrayList.class, LinkedList.class, ArrayDeque.class, Vector.class,
HashSet.class
// PriorityQueue/TreeSet/ConcurrentSkipListSet need comparator as
constructor argument
);
- protected Serializer<T> objectSerializer;
+ protected InternalFieldInfo[] fieldInfos;
protected final Serializer[] slotsSerializers;
public ChildCollectionSerializer(Fury fury, Class<T> cls) {
@@ -151,11 +154,14 @@ public class ChildContainerSerializers {
}
@Override
- public T copy(T originCollection) {
- if (objectSerializer == null) {
- objectSerializer = new ObjectSerializer<>(fury, type, false);
+ public Collection newCollection(Collection originCollection) {
+ Collection newCollection = super.newCollection(originCollection);
+ if (fieldInfos == null) {
+ List<Field> fields =
ReflectionUtils.getFieldsWithoutSuperClasses(type, superClasses);
+ fieldInfos = AbstractObjectSerializer.buildFieldsInfo(fury, fields);
}
- return fury.copyObject(originCollection, objectSerializer);
+ AbstractObjectSerializer.copyFields(fury, fieldInfos, originCollection,
newCollection);
+ return newCollection;
}
}
@@ -185,8 +191,8 @@ public class ChildContainerSerializers {
HashMap.class, LinkedHashMap.class, ConcurrentHashMap.class
// TreeMap/ConcurrentSkipListMap need comparator as constructor
argument
);
- private Serializer<T> objectSerializer;
private final Serializer[] slotsSerializers;
+ private InternalFieldInfo[] fieldInfos;
public ChildMapSerializer(Fury fury, Class<T> cls) {
super(fury, cls);
@@ -210,11 +216,14 @@ public class ChildContainerSerializers {
}
@Override
- public T copy(T originMap) {
- if (objectSerializer == null) {
- objectSerializer = new ObjectSerializer<>(fury, type, false);
+ public Map newMap(Map originMap) {
+ Map newMap = super.newMap(originMap);
+ if (fieldInfos == null || fieldInfos.length == 0) {
+ List<Field> fields =
ReflectionUtils.getFieldsWithoutSuperClasses(type, superClasses);
+ fieldInfos = AbstractObjectSerializer.buildFieldsInfo(fury, fields);
}
- return fury.copyObject(originMap, objectSerializer);
+ AbstractObjectSerializer.copyFields(fury, fieldInfos, originMap, newMap);
+ return newMap;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]