使用oql进行java堆分析:计算唯一的字符串

paw*_*que 14 java memory heap performance

我正在对现有的java软件进行内存分析.在oql中是否有一个sql'group by'等价来查看具有相同值但不同实例的对象的数量.

通过s.toString()从java.lang.String s group中选择count(*)

我想要获得重复字符串的列表以及重复的数量.这样做的目的是查看大数字的情况,以便可以使用String.intern()优化它们.

例:

"foo"    100
"bar"    99
"lazy fox"    50
Run Code Online (Sandbox Code Playgroud)

等等...

Joh*_*ing 22

以下是基于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;
    }
   }
  );
Run Code Online (Sandbox Code Playgroud)

它首先使用map()对所有String实例的调用以及为每个String创建或更新counts数组中的对象.每个对象都有一个string和一个count字段.

结果数组将为每个String实例包含一个条目,每个条目的count值都大于同一String的前一个条目.然后在count字段上对结果进行排序,结果如下所示:

{
count = 1028.0,
string = *null*
}

{
count = 1027.0,
string = *null*
}

{
count = 1026.0,
string = *null*
}

...
Run Code Online (Sandbox Code Playgroud)

(在我的测试中,String "*null*"是最常见的).

最后一步是使用一个函数对其进行过滤,该函数在每个String的第一次出现时返回true.它使用alreadyReturned数组来跟踪已包含的字符串.


Pal*_*esz 9

我会改用Eclipse Memory Analyzer.

  • 我非常喜欢你的建议,因为它很好地解决了这个问题.但是,我希望你能理解,为了编写oql,赏金归于Johan Kaving.我认为可能存在理解oql有用的情况.但是要感谢! (2认同)
  • 为此,请使用“打开查询浏览器”-&gt;“Java 基础知识”-&gt;“按值分组”。对于对象,选择“java.lang.String”,对于字段,选择“value”。 (2认同)