0

我目前正在查看这个愚蠢的小测试类的堆转储(在main方法的最后获取):

public class WeakRefTest {
    static final class RefObj1 { int i; }
    static final class RefObj2 { int j; }

    public static void main(String[] args) {
        Set<WeakReference<?>> objects = new HashSet<>();    
        RefObj1 obj1 = new RefObj1();
        RefObj2 obj2 = new RefObj2();
        for (int i = 0; i < 1000; i++) {
            objects.add(new WeakReference<RefObj1>(obj1));
            objects.add(new WeakReference<RefObj2>(obj2));
        }
    }
}

现在我试图弄清楚如何计算对特定类的引用objects。如果这是一个 SQL 数据库,那就很简单了:

select objects.className as referent, count(*) as cnt
  from java.lang.ref.WeakReference ref 
    inner join heapObjects objects on ref.referent = objects.objectId
  group by objects.className;

结果:

referent | cnt
===================
WeakRefTest$RefObj1 | 1000
WeakRefTest$RefObj2 | 1000

经过一番研究,我想我可以构建一个Eclipse MAT OQL查询,它为我提供了所涉及的类:

select DISTINCT OBJECTS classof(ref.referent) from java.lang.ref.WeakReference ref

唉,这不包括他们的计数,OQL 似乎不支持GROUP BY子句。任何想法如何获取此信息?

编辑添加:实际上,添加到的对象Set(显然也不是Set实现本身)都不受我的控制。很抱歉,修改RefObj1RefObj2不允许。

Edit2:我发现了这个关于在 jvisualvm 中使用 OQL 的相关问题,但事实证明OQL实际上是在堆转储中释放的 Javascript。我也会接受这样的事情。但是玩弄它并没有对我产生结果。如果情况发生变化,我会更新问题。

4

3 回答 3

1
  1. 打开直方图视图(有一个工具栏按钮,看起来像条形图)。
  2. 在直方图视图的第一行显示“Regex”,键入 WeakReference 以过滤视图。
  3. 找到 java.lang.ref.WeakReference 行,右键单击,然后选择“Show Objects By Class”->“By Outgoing References”。
  4. 结果视图应该总结被引用的对象,并根据需要按类分组。对象列应指示每个类的实例数。
于 2014-06-10T20:35:00.887 回答
0

I would use a Weak HashSet. You can just use set.size() to get the number of references still alive.

static final class RefObj1 { int i; }
static final class RefObj2 { int j; }

public static void main(String[] args) {
    Set objects = Collections.newSetFroMap(new WeakHashMap());
    RefObj1 obj1 = new RefObj1();
    RefObj2 obj2 = new RefObj2();
    for (int i = 0; i < 1000; i++) {
        objects.add(obj1);
        objects.add(obj2);
    }
    obj1 = null;
    System.gc();
    System.out.println("Objects left is " + objects.size());
}

I would expect this to print 0, 1 or 2 depending on how the objects are cleaned up.

于 2014-06-10T19:49:19.920 回答
0

您可以只在返回信息的对象中编写一个方法,然后从 Eclipse 中调用它...

由于您无法修改对象,那么下一个最好的方法就是以某种方法编写实用程序函数,您可以修改并从 eclipse 调试器中调用它。我不太了解 Eclipse,无法在不向源代码中插入内容的情况下帮助您做到这一点,抱歉。

于 2014-06-10T19:15:18.020 回答