diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java index 8904944189..4b0a8ba0e2 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java @@ -463,6 +463,30 @@ protected void copyEntry(Map originMap, Builder builder) { } } + protected void copyEntry(Map originMap, Object[] elements) { + ClassResolver classResolver = fury.getClassResolver(); + int index = 0; + for (Entry entry : originMap.entrySet()) { + K key = entry.getKey(); + if (key != null) { + ClassInfo classInfo = classResolver.getClassInfo(key.getClass(), keyClassInfoWriteCache); + if (!classInfo.getSerializer().isImmutable()) { + key = fury.copyObject(key, classInfo.getClassId()); + } + } + V value = entry.getValue(); + if (value != null) { + ClassInfo classInfo = + classResolver.getClassInfo(value.getClass(), valueClassInfoWriteCache); + if (!classInfo.getSerializer().isImmutable()) { + value = fury.copyObject(value, classInfo.getClassId()); + } + } + elements[index++] = key; + elements[index++] = value; + } + } + @SuppressWarnings("unchecked") protected final void readElements(MemoryBuffer buffer, int size, Map map) { Serializer keySerializer = this.keySerializer; diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ImmutableCollectionSerializers.java b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ImmutableCollectionSerializers.java index 4a69a25c52..ae31d90bbf 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ImmutableCollectionSerializers.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ImmutableCollectionSerializers.java @@ -118,6 +118,23 @@ public Collection newCollection(MemoryBuffer buffer) { } } + @Override + public Collection copy(Collection originCollection) { + if (Platform.JAVA_VERSION <= 8) { + throw new UnsupportedOperationException( + String.format( + "Only support jdk9+ java.util.ImmutableCollections deep copy. %s", + originCollection.getClass())); + } + Object[] elements = new Object[originCollection.size()]; + copyElements(originCollection, elements); + try { + return (List) listFactory.invoke(elements); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + @Override public Collection onCollectionRead(Collection collection) { if (Platform.JAVA_VERSION > 8) { @@ -150,6 +167,23 @@ public Collection newCollection(MemoryBuffer buffer) { } } + @Override + public Collection copy(Collection originCollection) { + if (Platform.JAVA_VERSION <= 8) { + throw new UnsupportedOperationException( + String.format( + "Only support jdk9+ java.util.ImmutableCollections deep copy. %s", + originCollection.getClass())); + } + Object[] elements = new Object[originCollection.size()]; + copyElements(originCollection, elements); + try { + return (Set) setFactory.invoke(elements); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + @Override public Collection onCollectionRead(Collection collection) { if (Platform.JAVA_VERSION > 8) { @@ -183,18 +217,25 @@ public Map newMap(MemoryBuffer buffer) { } @Override - public Map newMap(Map map) { - int numElements = map.size(); - if (Platform.JAVA_VERSION > 8) { - return new JDKImmutableMapContainer(numElements); - } else { - return new HashMap(numElements); + public Map copy(Map originMap) { + if (Platform.JAVA_VERSION <= 8) { + throw new UnsupportedOperationException( + String.format( + "Only support jdk9+ java.util.ImmutableCollections deep copy. %s", + originMap.getClass())); + } + int size = originMap.size(); + Object[] elements = new Object[size * 2]; + copyEntry(originMap, elements); + try { + if (size == 1) { + return (Map) map1Factory.invoke(elements[0], elements[1]); + } else { + return (Map) mapNFactory.invoke(elements); + } + } catch (Throwable e) { + throw new RuntimeException(e); } - } - - @Override - public Map onMapCopy(Map map) { - return onMapRead(map); } @Override diff --git a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/MapSerializers.java b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/MapSerializers.java index be4abfcbbb..a9f6a6263a 100644 --- a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/MapSerializers.java +++ b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/MapSerializers.java @@ -37,6 +37,7 @@ import org.apache.fury.memory.MemoryBuffer; import org.apache.fury.memory.Platform; import org.apache.fury.reflect.ReflectionUtils; +import org.apache.fury.resolver.ClassInfo; import org.apache.fury.resolver.ClassResolver; import org.apache.fury.serializer.ReplaceResolveSerializer; import org.apache.fury.serializer.Serializer; @@ -398,8 +399,17 @@ public Map read(MemoryBuffer buffer) { @Override protected void copyEntry(Map originMap, Map newMap) { + ClassResolver classResolver = fury.getClassResolver(); for (Entry entry : originMap.entrySet()) { - newMap.put(entry.getKey(), fury.copyObject(entry.getValue())); + V value = entry.getValue(); + if (value != null) { + ClassInfo classInfo = + classResolver.getClassInfo(value.getClass(), valueClassInfoWriteCache); + if (!classInfo.getSerializer().isImmutable()) { + value = fury.copyObject(value, classInfo.getClassId()); + } + } + newMap.put(entry.getKey(), value); } } }