java - 我可以使用 Instrumentation.getObjectSize 测量内存中列表(包括元素)的大小吗?

标签 java instrumentation

据我所知,java.lang.instrument.Instrumentation.getSize返回不带元素的大小(因为大小不取决于列表的数量。它是24字节) 。看起来很奇怪。未测量列表项是否正确?

最佳答案

Java 中对象的大小是固定的,因为 Java 和 C++ 一样,是一种静态类型语言。大小基本上对应于 class 文件中写入的内容。由于 class 文件布局是固定的,因此它的大小也是固定的。

ArrayList例如,看起来大致如下:

public class ArrayList implements List
{
    Object[] elementData;
    private int size;
}

任何 ArrayList 实例的大小将是 elementData 的大小(指向 Object[] 的指针) )、大小(int)和开销。所以 24 听起来不错。

这通常被称为浅尺寸

听起来你想要的是深度大小,即列表的大小+它引用的所有对象+这些对象引用的所有对象等。

使用instrumentation API 无法直接实现这一点,但通过一些hacky 反射+instrumentation 你也许能够得到它。基本思想是反射(reflect)对象并在所有引用的对象上递归调用 getObjectSize(),跳过循环引用。

大致的内容:

public class DeepSizeCounter {
    private HashSet<Object> counted = new HashSet<>();
    private long size = 0;

    public long getSizeDeep(Object x) throws Exception {
        counted.clear();
        size = 0;
        computeSizeDeep(x);
        return size;
    }

    private void computeSizeDeep(Object x) throws Exception {
        if (x != null && !counted.contains(x)) {
            counted.add(x);
            size += instrumentation.getObjectSize(x);
            if (x.getClass().isArray()) {
                if (!x.getClass().getComponentType().isPrimitive())
                    for (Object y : (Object[]) x)
                        computeSizeDeep(y);
            } else {
                for (Field f : x.getClass().getDeclaredFields()) {
                    if (!f.getType().isPrimitive() && (f.getModifiers() & Modifier.STATIC) == 0) {
                        f.setAccessible(true);
                        computeSizeDeep(f.get(x));
                    }
                }
            }
        }
    }
}

用作:

long totalSize = new DeepSizeCounter().getSizeDeep(myList);

请注意,这种方法不可靠,因为对象可能具有对某些全局状态的反向引用,而您无法自动区分这些状态,因此最终可能会计数太多对象。此外,如果访问控制处于打开状态,Field.setAccessible() hack 将不起作用,并且您将无法计算任何非公共(public)成员。

关于java - 我可以使用 Instrumentation.getObjectSize 测量内存中列表(包括元素)的大小吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54162849/

相关文章:

java - 如何将双线底部边框应用于 iText 中的单元格

java - 如何从服务器套接字读取unicode字符

java - 在 try-finally block 中嵌入方法的现有代码 (2)

java - 无法解析 : Intent when instrumentation-testing android activities 的 Activity

java - bfs java代码中的尖括号

java - Clojure nil vs Java null?

java - 使用类别注释在 IntelliJ 中运行 JUnit 测试

javassist.CannotCompileException : [source error] no such class: TestDebug

java - ActivityInstrumentationTestCase2 问题 - 由于我正在为其编写测试的代码中的 invalidate() 调用导致测试挂起

java - 如何知道 JUnit 测试触及了哪些类