Размер объектов в Java фиксирован, потому что Java, как и C ++, является языком статической типизации. Размер в основном соответствует тому, что написано в файле class
. Поскольку макет файла class
фиксирован, то же самое относится и к его размеру.
Например, ArrayList
выглядит примерно так:
public class ArrayList implements List
{
Object[] elementData;
private int size;
}
Размер любого ArrayList
экземпляра будет иметь размер elementData
(указатель на Object[]
), size
(int
) и накладные расходы. Итак, 24 звучат о праве.
Это часто называют мелким размером .
Звучит так, будто вы хотите получить глубокий размер , то есть размер списка + всех объектов, к которым он относится + все объекты, к которым относятся эти объекты и т. Д.
Это невозможно сделать напрямую с помощью API инструментовки, но с некоторыми хакерскими размышлениями + инструментарием вы сможете его получить. Основная идея состоит в том, чтобы отразить объект и рекурсивно вызвать 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()
не будет работать, и вы не сможете сосчитать ни одного непубличного участника.