Могу ли я измерить размер списка в памяти, включая элементы, используя Instrumentation.getObjectSize? - PullRequest
0 голосов
/ 12 января 2019

Насколько я вижу, java.lang.instrument.Instrumentation.getSize возвращает размер без элементов (так как размер не зависит от номера списка. Это 24 байта). Выглядит странно Это правильно, что элементы списка не измеряются?

1 Ответ

0 голосов
/ 12 января 2019

Размер объектов в 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() не будет работать, и вы не сможете сосчитать ни одного непубличного участника.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...