据我所知java.lang.instrument.Instrumentation.getSize
返回不带元素的大小(因为大小不取决于列表的数目。它是24个字节)。看起来很奇怪列表项未被测量是否正确?
答案 0 :(得分:2)
Java中对象的大小是固定的,因为Java与C ++一样,是一种静态类型的语言。大小基本上与class
文件中写入的内容相对应。由于class
的文件布局是固定的,因此其大小也是固定的。
例如ArrayList
的外观大致如下:
public class ArrayList implements List
{
Object[] elementData;
private int size;
}
任何 ArrayList
实例的大小将是elementData
(指向Object[]
的指针),size
({{ 1}})和开销。因此,大约有24种声音是正确的。
通常称为 浅尺寸 。
听起来像您想要的是 深尺寸 ,即列表 + 所引用的所有对象的尺寸 + 这些对象引用的所有对象,等等。
使用工具API不可能直接做到这一点,但是通过一些骇人的反射+工具,您也许可以得到它。基本思想是反映对象并在所有引用的对象上递归调用int
,跳过循环引用。
大致情况:
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);
黑客将无法使用,您将无法计算任何非公开成员。