使用Gson将JSON转List时出现OutOfMemoryError问题及解决咨询
解决Gson转换JSON数组时的OutOfMemoryError问题
问题根源
你的代码中jsonArray.toString()会把整个JSON数组序列化为一个超大字符串,额外占用大量内存;后续Gson解析该字符串生成List时,内存里同时存在巨型字符串和解析后的List对象,双重内存开销直接触发了OOM。
具体解决方法
1. 逐个解析JSONArray元素(优先方案)
不要一次性把整个JSONArray转成字符串,而是遍历数组内的每个元素,逐个解析为目标对象,内存仅需容纳单个对象的大小,而非整个数组的字符串副本:
@Nullable public <T> List<T> getConvertedListFromJson(JSONArray jsonArray, Class<T> type) { if (jsonArray == null || jsonArray.length() == 0) { return Collections.emptyList(); } // Gson是线程安全的,建议全局复用,不要每次新建 private static final Gson GSON = new Gson(); List<T> resultList = new ArrayList<>(jsonArray.length()); for (int i = 0; i < jsonArray.length(); i++) { try { JsonElement element = GSON.toJsonTree(jsonArray.get(i)); T item = GSON.fromJson(element, type); resultList.add(item); } catch (JSONException e) { // 可根据业务需求处理单个元素解析失败的情况,比如跳过或打日志 e.printStackTrace(); } } return resultList; }
2. 复用Gson实例
Gson对象是线程安全的,不要在每次方法调用时新建Gson gson = new Gson();,将其定义为类的静态成员变量,减少对象创建的内存开销。
3. 流式解析(如果原始数据来自文件/输入流)
如果JSON数据最初是从文件或网络输入流读取的,不要先把整个数据加载成JSONArray,直接用Gson的JsonReader流式读取解析,内存占用极低:
public <T> List<T> parseLargeJsonList(InputStream inputStream, Class<T> type) throws IOException { private static final Gson GSON = new Gson(); JsonReader reader = new JsonReader(new InputStreamReader(inputStream)); List<T> list = new ArrayList<>(); reader.beginArray(); while (reader.hasNext()) { T item = GSON.fromJson(reader, type); list.add(item); } reader.endArray(); reader.close(); return list; }
4. 临时调整堆内存(治标不治本)
如果是Android应用,可在AndroidManifest.xml的application标签里添加android:largeHeap="true";如果是JVM应用,启动时增加-Xmx参数(比如-Xmx512m)增大堆内存。但这只是临时缓解,优先采用前面的代码优化方案。
内容的提问来源于stack exchange,提问作者user9298460
相关产品推荐
相关产品推荐

