我对现有的
java软件进行内存分析.在oql中有一个sql’group by’等价物,以查看具有相同值但不同实例的对象的计数.
选择count(*)
来自java.lang.String s
group by s.toString()
我想实现重复字符串的列表以及重复的数量.这样做的目的是查看大量的情况,以便可以使用String.intern()进行优化.
例:
"foo" 100 "bar" 99 "lazy fox" 50
等等…
解决方法
以下是基于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实例使用map()调用,并为每个String创建或更新计数数组中的对象.每个对象都有一个字符串和一个计数字段.
结果数组将为每个String实例包含一个条目,每个条目的计数值大于同一个String的上一个条目.
然后将结果按计数字段排序,结果如下所示:
{ count = 1028.0,string = *null* } { count = 1027.0,string = *null* } { count = 1026.0,string = *null* } ...
(在我的测试中,String“* null *”是最常见的).
最后一步是使用为每个String的第一次出现返回true的函数来过滤它.它使用已经返回的数组来跟踪已经包含的字符串.