以下内容基于Peter Dolberg的答案,可以在VisualVM OQL控制台中使用:
var counts={};
var alreadyReturned={};
filter(
sort(
map(heap.objects("java.lang.String"),
function(heapString){
if( ! counts[heapString.toString()]){
counts[heapString.toString()] = 1;
} else {
counts[heapString.toString()] = counts[heapString.toString()] + 1;
}
return { string:heapString.toString(), count:counts[heapString.toString()]};
}),
'lhs.count < rhs.count'),
function(countObject) {
if( ! alreadyReturned[countObject.string]){
alreadyReturned[countObject.string] = true;
return true;
} else {
return false;
}
}
);
它首先对所有 String 实例使用调用,并为每个 String 创建或更新数组中的对象。每个对象都有一个和一个字段。map()
counts
string
count
生成的数组将包含每个 String 实例的一个条目,每个条目的值都比同一 String 的上一个条目大一个。然后,在字段上对结果进行排序,结果如下所示:count
count
{
count = 1028.0,
string = *null*
}
{
count = 1027.0,
string = *null*
}
{
count = 1026.0,
string = *null*
}
...
(在我的测试中,字符串是最常见的)。"*null*"
最后一步是使用一个函数对此进行筛选,该函数为每个 String 的第一次出现返回 true。它使用数组来跟踪已包含哪些字符串。alreadyReturned