1. 问题描述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| private JSONArray getChildInfo(String root, Set<String> childrens) throws JSONException { JSONArray rtJA = new JSONArray(); for (String child : childrens) { String key = generateKey(root,child); if (isVisited.contains(key)) { continue; } String simpleTableName = child.substring(child.indexOf('@')+1); effectNode.add(simpleTableName); isVisited.add(key); JSONObject jsonObject = new JSONObject(); if(nodechildrens.containsKey(child)){ JSONArray temp = getChildInfo(child, nodechildrens.get(child)); if (!temp.isEmpty()) { jsonObject.put("children", temp.toJSONString()); } else { jsonObject.put("children", ""); } } else { jsonObject.put("children", ""); } jsonObject.put("name",simpleTableName); isVisited.remove(key); rtJA.add(jsonObject.toString()); } return rtJA; }
|
temp.toJSONString()报错
1
| fastjson java.lang.OutOfMemoryError: Java heap space
|
因为代码是里面用了递归,一开始以为是代码问题,debug了许久,没发现哪里逻辑错了。
想着之前学过JVM,就试着通过堆快照分析哪里错了
2. 堆快照分析
首先,设置jvm参数(jdk 1.8),使发生堆溢出时保存快照
1
| -XX:HeapDumpPath=/Users/wangji/Desktop/dumpfile.hprof -XX:+HeapDumpOnOutOfMemoryError
|
之后,通过MAT分析快照

发现有个String有455MB的大小,使用fastjson时,又占了445MB,整体接近1G,这里才是发生堆溢出的原因。
知道原因后,递归过程中对字符串进行简化操作(去除”\“和其他多余的字符),最终解决问题
简化代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| private JSONArray getChildInfo(String root, Set<String> childrens) throws JSONException { JSONArray rtJA = new JSONArray(); for (String child : childrens) { String key = generateKey(root,child); if (isVisited.contains(key)) { continue; } String simpleTableName = child.substring(child.indexOf('@')+1); effectNode.add(simpleTableName); isVisited.add(key); JSONObject jsonObject = new JSONObject(); if(nodechildrens.containsKey(child)){ JSONArray temp = getChildInfo(child, nodechildrens.get(child)); if (!temp.isEmpty()) { jsonObject.put("children", modifyString(temp.toJSONString(),false)); } else { jsonObject.put("children", ""); } } else { jsonObject.put("children", ""); } jsonObject.put("name",simpleTableName); isVisited.remove(key); rtJA.add(jsonObject.toString()); } return rtJA; }
private String modifyString(String origin, boolean removeSide) { String out = origin.replaceAll("\\\\",""); out = out.replaceAll("\"\\{","{"); out = out.replaceAll("\\}\"","}"); out = out.replaceAll("\"\\[","["); out = out.replaceAll("\\]\"","]"); if (removeSide) { out = out.substring(1,out.length()-1); } return out; }
|