1

我想构建一个 OQL 查询,使用该查询从特定包中的类中递归打印出 JVM 堆转储的所有静态数据。我知道递归遍历内存引用可能存在很多问题,但是(至少在最初)我会通过设置深度阈值来缓解这些问题。

根据文档,类有一个statics字段,该字段又应由names 和s组成value

statics - 类的静态字段的名称、值对。

我已经停止使用表达式获取每个静态字段的名称,field.name并且不知道如何迭代对象的非静态字段。我目前有:

select map(
    filter(
        filter(heap.classes(), "/com.heap./.test(it.name)"),
        function (clazz) {
            if (clazz.statics) {
                return true;
            }
            return false;
        }
    ), function (clazz) {
        var res = '';
        res += toHtml(clazz.name) + " : " + toHtml(clazz.statics) + "<br>";
        map(clazz.statics, function (field) {
            res += "--" + toHtml(field) + "," + toHtml(field.name) + "," + toHtml(field.state) +"<br>";
        });
        return res + "<br>";
    }
)

并得到以下输出:

com.heap.dump.DataHolder : { :sun.misc.Launcher$AppClassLoader#1, }
--sun.misc.Launcher$AppClassLoader#1,null,null

com.heap.dump.HeapDumperTest : { dataHolder:com.heap.dump.DataHolder#1, mutableStaticState:java.lang.String#225, :sun.misc.Launcher$AppClassLoader#1, }
--com.heap.dump.DataHolder#1,null,java.lang.String#224
--java.lang.String#225,null,null
--sun.misc.Launcher$AppClassLoader#1,null,null

com.heap.dump.Main : { :sun.misc.Launcher$AppClassLoader#1, }
--sun.misc.Launcher$AppClassLoader#1,null,null

我正在迭代clazz.statics使用该map()函数,遵循这个答案

看起来field参数只是字段的值,field.name一如既往null并且field.state实际上检索对象之一(com.heap.dump.DataHolder.state)上的字段。

主要问题:

  • 在迭代静态字段时,除了值之外,如何获取字段名称?
  • 一旦有了要遍历的对象/实例,如何迭代该对象的非静态字段(名称和值)?这种获取字段值的方法,就像field.state语句一样,只有在我已经知道字段名称的情况下才有帮助,这里不是这种情况。

附加问题:

  • 如何过滤掉空名称的 AppClassLoader 静态字段?
  • 我是否使用了错误的工具来完成这项工作?VisualVM 的 OQL 是否有更简单的替代方案?
4

1 回答 1

1

statics是一张地图,所以你应该用for(..)它来迭代它。我更新了你的查询。见下文:

select map(
    filter(
        filter(heap.classes(), "/com.heap./.test(it.name)"),
        function (clazz) {
            if (clazz.statics) {
                return true;
            }
            return false;
        }
    ), function (clazz) {
        var res = '';
        res += toHtml(clazz.name) + " :<br>";
        for (field in clazz.statics) {
            res += "-- " + toHtml(field) + ", " + toHtml(clazz.statics[field]) +"<br>";
        }
        return res + "<br>";
    }
)
于 2020-02-12T08:02:34.057 回答