You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求值为复杂对象的Map深拷贝替代方案(原Gson存内存问题)

Map深拷贝的Gson替代方案(解决内存泄漏问题)

问题背景

  • 此前使用Gson实现Map深拷贝,能保证修改拷贝后的Map不会影响原Map,但出现线程持有问题:堆转储中存在大量Gson相关条目,内存持续增长,最终导致请求被拒。
  • 尝试过orgMap.clone()、new HashMap<>(orgMap)、copymap.putAll(orgMap)这些浅拷贝方式,均无法对Map的value对象实现深拷贝——修改拷贝Map中的value会同时影响原Map和拷贝后的Map。

堆转储线程调用栈

Processing Thread 13running , holding [ at
com.google.gson.stream.JsonReader.doPeek(JsonReader.java:593) at
com.google.gson.stream.JsonReader.peek(JsonReader.java:433) at
com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:244) at
com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:241) at
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.readIntoField(ReflectiveTypeAdapterFactory.java:212) at
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$FieldReflectionAdapter.readField(ReflectiveTypeAdapterFactory.java:433) at
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:393) at
com.google.gson.Gson$FutureTypeAdapter.read(Gson.java:1367) at
com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) at
com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82) at
com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) at
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.readIntoField(ReflectiveTypeAdapterFactory.java:212) at
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$FieldReflectionAdapter.readField(ReflectiveTypeAdapterFactory.java:433) at
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:393) at
com.google.gson.Gson$FutureTypeAdapter.read(Gson.java:1367) at
com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) at
com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82) at
com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) at
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.readIntoField(ReflectiveTypeAdapterFactory.java:212) at
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$FieldReflectionAdapter.readField(ReflectiveTypeAdapterFactory.java:433) at
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:393) at
com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) at
com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:186) at
com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:144) at
com.google.gson.Gson.fromJson(Gson.java:1227) at
com.google.gson.Gson.fromJson(Gson.java:1137) at
com.google.gson.Gson.fromJson(Gson.java:1047) at
com.google.gson.Gson.fromJson(Gson.java:1014) at
com.util.getDeepCopyOfMap(Utils.java:2398) at
com.util.ParameterPopulation.applyFiltering(ParameterPopulation.java:800) at
com.util.ParameterPopulation.populateSchemaParameters(ParameterPopulation.java:506) at
com.util.ParameterPopulation.formAvroRequestBasedOnSession(ParameterPopulation.java:440) at
com.util.ParameterPopulation.populateLocationRelatedParameters(ParameterPopulation.java:1343) at
com.util.ParameterPopulation.localProcess(ParameterPopulation.java:294) at
com.util.AbstractProcessingActivity.process(AbstractProcessingActivity.java:30) at
com.util.TransactionImpl.run(TransactionImpl.java:415) at
com.util.TransactionHandlerImpl$FaultTolerantTransaction.run(TransactionHandlerImpl.java:466) at
java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.20/ThreadPoolExecutor.java:1128) at
java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.20/ThreadPoolExecutor.java:628) at
java.lang.Thread.run(java.base@11.0.20/Thread.java:829)

可行替代方案

1. 手动实现深拷贝

针对Map中Value的具体类型,编写自定义拷贝逻辑,精准控制每个Value的深拷贝:

public static <K, V> Map<K, V> deepCopyMap(Map<K, V> original, Function<V, V> valueCopier) {
    Map<K, V> copiedMap = new HashMap<>();
    for (Map.Entry<K, V> entry : original.entrySet()) {
        copiedMap.put(entry.getKey(), valueCopier.apply(entry.getValue()));
    }
    return copiedMap;
}

示例:若Value为自定义User对象,可传入user -> new User(user.getId(), user.getName(), user.getAddress().clone())作为拷贝函数,确保嵌套对象也被深拷贝。

2. 使用Apache Commons Lang的SerializationUtils

通过序列化实现通用深拷贝,要求Map的Key和Value均实现Serializable接口:

import org.apache.commons.lang3.SerializationUtils;

public static <K, V> Map<K, V> deepCopyMap(Map<K, V> original) {
    return SerializationUtils.clone(original);
}

注意:该方式性能略低,且不支持不可序列化的类型。

3. 基于Jackson实现深拷贝

与Gson逻辑类似,但Jackson的线程安全性更优,内存泄漏风险更低:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;

private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

public static <K, V> Map<K, V> deepCopyMap(Map<K, V> original) throws IOException {
    String json = OBJECT_MAPPER.writeValueAsString(original);
    return OBJECT_MAPPER.readValue(json, new TypeReference<Map<K, V>>() {});
}

建议使用单例ObjectMapper实例,避免重复创建带来的性能开销。

4. 模型类实现Cloneable接口

若Value为自定义模型类,让类实现Cloneable并重写clone()方法,实现自身的深拷贝逻辑:

public class User implements Cloneable {
    private String id;
    private String name;
    private Address address; // 嵌套对象需同样实现Cloneable

    @Override
    protected Object clone() throws CloneNotSupportedException {
        User cloned = (User) super.clone();
        cloned.address = (Address) address.clone(); // 深拷贝嵌套对象
        return cloned;
    }
}

拷贝Map时遍历每个Entry,调用Value的clone()方法放入新Map即可。


内容的提问来源于stack exchange,提问作者Ganesh ram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 15:47:07