[英]VisualVM heap dump "Summary" shows way more roots than "Objects->Preset: GC Roots" shows, what does it mean?
我怀疑由 JNI 代码引起的缓慢 memory 泄漏。 我在连续堆转储爬升的摘要中看到了 GC Roots #。 两个小时后,它显示了 470,000 个 GC 根,六个小时后,显示了近一百万个 GC 根,33 小时后显示了超过 700 万个 GC 根。
但是,当我查看说有 700 万个 GC 根的 Head Dump 时,我选择了“对象”视图和“GC 根”预设,我选择了 select 聚合“类型”。 此列表显示的对象总数少于 15,000 个:
那七百万个根在哪里?
不同的 GC 根可以引用同一个 object 实例。 这解释了差异,因为从“GC root”视图计数显示的唯一实例数。 您可以使用 OQL 找到更多详细信息。 首先让我们显示特定 GC 类型的 GC 根数:
printHistogram()
function printHistogram() {
var roots = heap.roots()
var histoMap = new Array();
var result = new Array();
var cnt = 0;
while (roots.hasMoreElements()) {
var root = roots.nextElement();
var type = root.type;
if (histoMap[type] == undefined) {
histoMap[type] = 1;
} else {
histoMap[type]++;
}
}
for (var key in histoMap){
if (histoMap.hasOwnProperty(key)) {
result[cnt++] = { key: key, count: histoMap[key] };
}
return map(sort(result, "rhs.count - lhs.count"), '"Root count: "+it.count+" for type: "+it.key');
}
针对您的堆转储运行此查询会产生:
Root count: 12878043 for type: JNI local
Root count: 7858 for type: JNI global
Root count: 3599 for type: sticky class
Root count: 1631 for type: Java frame
Root count: 146 for type: thread object
Root count: 7 for type: monitor used
我们可以看到大多数 GC 根是“JNI 本地”类型。 让我们看看有多少“JNI 本地”根指向同一个 object 实例。 我们可以将上面的查询修改为:
printHistogram()
function printHistogram() {
var roots = heap.roots()
var histoMap = new Array();
var result = new Array();
var cnt = 0;
while (roots.hasMoreElements()) {
var root = roots.nextElement();
if (root.type == "JNI local") {
var objid = root.id;
if (histoMap[objid] == undefined) {
histoMap[objid] = 1;
} else {
histoMap[objid]++;
}
}
}
for (var key in histoMap){
if (histoMap.hasOwnProperty(key)) {
result[cnt++] = { key: key, count: histoMap[key] };
}
}
return map(sort(result, "rhs.count - lhs.count"), '"Root count: "+it.count+" for object: "+toHtml(heap.findObject(it.key))');
}
结果如下:
Root count: 6439020 for object: java.lang.String#44429
Root count: 6439020 for object: java.lang.String#55081
Root count: 1 for object: java.nio.DirectByteBuffer#9
Root count: 1 for object: java.util.ArrayList#22281
Root count: 1 for object: java.lang.String#71518
我们可以看到两个字符串java.lang.String#44429
和java.lang.String#55081
负责大量的 GC 根。 他们每个都有 650 万个 GC 根。
那些“JNI 本地”GC 根是从框架ca.digitalrapids.kayak.jni.KayakNativeWorkerThread.runNative (Native Method)
的MessageDispatherThread-1 (tid=216)
引用的。 请参阅下面的屏幕截图:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.