据我所知,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/