В Java, как лучше всего определить размер объекта?

У меня есть приложение, которое читает файл CSV с кучами строк данных. Я даю пользователю сводную информацию о количестве строк на основе типов данных, но хочу убедиться, что я не читаю слишком много строк данных и вызываю OutOfMemoryErrors. Каждая строка переводится в объект. Есть ли простой способ узнать размер этого объекта программно? Есть ли ссылка, которая определяет, насколько большие примитивные типы и ссылки на объекты для VM?

Прямо сейчас у меня есть код, который читает до 32 000 строк , но я также хотел бы, чтобы код читал как можно больше строк, пока я не использовал 32 МБ памяти. Может быть, это другой вопрос, но я все еще хотел бы знать.

9.09.2008 17:07:03
Я добавил своего агента с помощью конфигов mvn и объяснил, как здесь: stackoverflow.com/a/36102269/711855
juanmf 19.03.2016 13:28:17
25 ОТВЕТОВ
РЕШЕНИЕ

Вы можете использовать пакет java.lang.instrument

Скомпилируйте и поместите этот класс в JAR:

import java.lang.instrument.Instrumentation;

public class ObjectSizeFetcher {
    private static Instrumentation instrumentation;

    public static void premain(String args, Instrumentation inst) {
        instrumentation = inst;
    }

    public static long getObjectSize(Object o) {
        return instrumentation.getObjectSize(o);
    }
}

Добавьте следующее к вашему MANIFEST.MF:

Premain-Class: ObjectSizeFetcher

Используйте getObjectSize:

public class C {
    private int x;
    private int y;

    public static void main(String [] args) {
        System.out.println(ObjectSizeFetcher.getObjectSize(new C()));
    }
}

Вызвать с:

java -javaagent:ObjectSizeFetcherAgent.jar C
458
28.06.2016 18:24:59
@ Стефан Хороший намек! Можете ли вы сказать, какой будет размер byte[0], byte[1], byte[5], int[0], int[1], int[2]используя подход , вы описали? Было бы хорошо, если бы результаты включали накладные расходы на длину массива и выравнивание памяти.
dma_k 8.03.2010 11:28:05
Я попробовал это и получил странные и бесполезные результаты. Строки были всегда 32, независимо от размера. Я подумал, что это, возможно, размер указателя, но для другого неизменного класса, который я создал, я получил 24. Он хорошо работает для примитивов, но тогда вам не нужна программа, чтобы сказать вам, насколько большой символ.
Brel 16.09.2011 12:39:46
@ Это решение является только «приблизительным объемом памяти, потребляемой указанным объектом», как указано в документации. Также я предполагаю, что авторы решили установить размер строки в 32 байта (только указатель?) Из-за пула строк Java, что затрудняет определение того, является ли экземпляр String общим (хранится в пуле) или местный и уникальный для класса.
Andrei I 17.07.2013 08:33:48
Как я могу использовать ObjectSizeFetcher, если не экспортирую jar? У меня есть тестовый Java-проект в Eclipse.
Yura Shinkarev 5.08.2013 18:40:01
@brel Причина, по которой длина строки составляет всего 32 байта независимо от фактической длины, заключается в том, что часть строки переменной длины хранится в char [], который является ее собственным объектом. Чтобы получить истинный размер объекта, вам нужно добавить размер самого себя и размер каждого объекта, на который он ссылается.
tombrown52 31.05.2018 16:05:44

Я сомневаюсь, что вы хотите сделать это программно, если только вы не хотите сделать это один раз и сохранить его для будущего использования. Это дорогая вещь. В Java нет оператора sizeof (), и даже если бы он был, он бы только подсчитывал стоимость ссылок на другие объекты и размер примитивов.

Один из способов сделать это - сериализовать объект в файл и посмотреть на размер файла, например так:

Serializable myObject;
ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("obj.ser"));
oos.write (myObject);
oos.close ();

Конечно, это предполагает, что каждый объект является отдельным и не содержит непереходных ссылок на что-либо еще.

Другая стратегия состояла бы в том, чтобы взять каждый объект и изучить его элементы путем отражения и сложить размеры (логическое значение & byte = 1 байт, short & char = 2 байта и т. Д.), Пробираясь вниз по иерархии членства. Но это утомительно и дорого и в итоге делает то же самое, что и стратегия сериализации.

-6
9.09.2008 17:11:35
Я бы сериализовал его в byte [], используя ByteArrayOutputStream. Это было бы намного быстрее, чем записать его в файл.
ScArcher2 9.09.2008 17:21:47
@KorayTugay Определение размера объекта в байтах уже является дорогостоящей операцией. Запись каждого объекта на диск для определения размера, просто заставит его ползти ...
HammerNL 19.12.2017 10:24:50
Формат сериализованного объекта полностью отличается от формата объекта в куче памяти. В частности, дескриптор класса объекта (и всех его сериализуемых суперклассов) записывается в поток. Таким образом, написание простого экземпляра java.lang.Integerдает около 80 байтов, где представление кучи обычно равно 32 (в отличие от представления потока объекта, представление кучи зависит от размеров указателя и выравнивания объекта). Напротив, для сериализованной nullссылки требуется один байт вместо четырех или восьми байтов в памяти кучи.
Holger 9.05.2018 11:50:51

Нет вызова метода, если это то, что вы просите. С небольшим исследованием, я полагаю, вы могли бы написать свой собственный. Конкретный экземпляр имеет фиксированный размер, полученный из числа ссылок и примитивных значений плюс данные учета экземпляра. Вы бы просто шли по графу объектов. Чем менее разнообразны типы строк, тем легче.

Если это слишком медленно или просто больше проблем, чем стоит, всегда найдется старое доброе правило подсчета строк.

2
9.09.2008 17:15:40

Если вы просто хотите узнать, сколько памяти используется в вашей JVM и сколько свободно, вы можете попробовать что-то вроде этого:

// Get current size of heap in bytes
long heapSize = Runtime.getRuntime().totalMemory();

// Get maximum size of heap in bytes. The heap cannot grow beyond this size.
// Any attempt will result in an OutOfMemoryException.
long heapMaxSize = Runtime.getRuntime().maxMemory();

// Get amount of free memory within the heap in bytes. This size will increase
// after garbage collection and decrease as new objects are created.
long heapFreeSize = Runtime.getRuntime().freeMemory();

редактирование: я подумал, что это может быть полезно, так как автор вопроса также заявил, что хотел бы иметь логику, которая обрабатывает «чтение как можно большего количества строк, пока я не использую 32 МБ памяти».

37
16.07.2014 16:08:47
Это не хорошее решение, так как вы никогда не знаете, когда произойдет сборка мусора или сколько дополнительной памяти будет выделено для кучи сразу.
Nick Fortescue 9.09.2008 17:24:34
Это правда, и я бы не собирался решать этот главный вопрос этого поста, но это может помочь ему программно узнать, когда он приближается к достижению максимального размера кучи.
matt b 9.09.2008 17:25:55
Другая проблема этого решения - когда вы находитесь в многопоточной среде (например, на веб-сервере). Возможно, что другие потоки были в исполнении и потребляли память. В этом приближении вы рассчитываете используемую память во всей виртуальной машине.
angelcervera 24.02.2013 10:34:48
Еще одним недостатком является то, что freeMemory возвращает приближение. Попробуйте создать объект javax.crypto.Cipher. Разница между двумя вызовами freeMemory (для оценки размера шифра) не постоянна!
Eugen 9.05.2013 15:08:50
Я считаю, что вы можете форсировать сборку мусора, так что вы можете сделать некоторые вещи в этом подходе.
matanster 12.02.2015 15:30:02

Вы должны ходить по объектам, используя отражение. Будьте осторожны, как вы делаете:

  • Простое выделение объекта имеет некоторые издержки в JVM. Количество зависит от JVM, поэтому вы можете сделать это значение параметром. По крайней мере, сделайте его константой (8 байт?) И примените его ко всему выделенному.
  • То, что byteтеоретически 1 байт не означает, что он занимает только один в памяти.
  • В ссылках на объекты будут циклы, так что вам нужно будет сохранять HashMapили иногда использовать объект-равно в качестве компаратора для устранения бесконечных циклов.

@jodonnell: мне нравится простота вашего решения, но многие объекты не являются сериализуемыми (поэтому это может вызвать исключение), поля могут быть временными, а объекты могут переопределять стандартные методы.

11
9.09.2008 17:19:48
Разве размеры различных примитивов не определены в спецификации Java? (§2.4.1)
erickson 9.09.2008 17:25:03
Не в смысле «сколько памяти она занимает», вот в чем вопрос. Только в том смысле, как они работают. Например, байты, символы и шорты занимают целое слово в стеке Java, даже если они работают с округлением и т. Д.
Jason Cohen 9.09.2008 17:27:35
Это похоже на измерение размера, как показано Хайнцем в его Информационном бюллетене № 78: javaspecialists.eu/archive/Issue078.html . Я использовал это. Его подход работает.
Peter Kofler 21.03.2010 09:26:09

Вы должны измерить его инструментом или оценить вручную, и это зависит от используемой вами JVM.

Существует несколько фиксированных накладных расходов на объект. Это зависит от JVM, но я обычно оцениваю 40 байтов. Тогда вы должны посмотреть на членов класса. Ссылки на объекты составляют 4 (8) байта в 32-битной (64-битной) JVM. Примитивные типы:

  • логическое значение и байт: 1 байт
  • char и short: 2 байта
  • int и float: 4 байта
  • длинный и двойной: 8 байт

Массивы следуют тем же правилам; то есть это ссылка на объект, которая занимает 4 (или 8) байта в вашем объекте, а затем его длину, умноженную на размер его элемента.

Попытка сделать это программно с помощью вызовов Runtime.freeMemory()просто не даст вам большой точности из-за асинхронных вызовов сборщика мусора и т. Д. Профилирование кучи с помощью -Xrunhprof или других инструментов даст вам наиболее точные результаты.

8
26.12.2012 04:04:16
@erickson Я не уверен насчет sizeof (логическое значение) == 1, просматривающего эту ветку ( stackoverflow.com/questions/1907318/… ). Можете ли вы прокомментировать это?
dma_k 8.03.2010 11:22:15
@dma_k, Java не имеет настоящих логических значений. Размер логического значения составляет 4 байта вне массивов и 1 байт внутри boolean[]. На самом деле все примитивы не двойного / длинного типа имеют размер 4 байта. Последним по 8 (в ответе их тоже
bestsss 25.12.2012 14:43:02
@bestsss: Точнее, минимальное выделение памяти зависит от платформы и реализации JVM. Также объекты в куче выровнены, поэтому после суммирования всех размеров нужно округлить.
dma_k 29.12.2012 09:52:44

Во-первых, «размер объекта» не является четко определенной концепцией в Java. Вы можете иметь в виду сам объект, только с его членами, объектом и всеми объектами, на которые он ссылается (граф ссылок). Вы можете указать размер в памяти или размер на диске. И JVM разрешено оптимизировать такие вещи, как строки.

Поэтому единственный правильный способ - спросить JVM с хорошим профилировщиком (я использую YourKit ), что, вероятно, не то, что вы хотите.

Однако из приведенного выше описания звучит так, что каждая строка будет автономной и не будет иметь большого дерева зависимостей, поэтому метод сериализации, вероятно, будет хорошим приближением для большинства JVM. Самый простой способ сделать это заключается в следующем:

 Serializable ser;
 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 ObjectOutputStream oos = new ObjectOutputStream(baos);
 oos.writeObject(ser);
 oos.close();
 return baos.size();

Помните, что если у вас есть объекты с общими ссылками, это не даст правильного результата, и размер сериализации не всегда будет соответствовать размеру в памяти, но это хорошее приближение. Код будет немного более эффективным, если вы инициализируете размер ByteArrayOutputStream разумным значением.

61
3.02.2018 15:52:59
Мне нравится этот подход. Насколько далеко вы были с точки зрения размера объекта.
Berlin Brown 24.07.2009 17:56:05
Очень просто и эффективно. Другие методы слишком беспорядочные (особенно внутри Eclipse RCP). Спасибо.
marcolopes 24.04.2012 16:18:52
Сериализация не будет отслеживать переходные переменные, и метод сериализации по умолчанию записывает строки в UTF-8, поэтому любые символы ANSI будут занимать только один байт. Если у вас много строк, ваш размер будет настолько бесполезным.
TMN 9.07.2012 18:45:57
хотя это может не дать точного размера, для моих нужд мне нужно было только сравнение между 2 объектами, а SizeOf не будет инициализироваться из веб-приложения. Спасибо!
Isaac 30.10.2012 22:57:46
Хорошая рекомендация YourKit . Другие альтернативы - VirtualVM и jvmmonitor
angelcervera 24.02.2013 10:46:44

Несколько лет назад в Javaworld была статья по определению размера составных и потенциально вложенных объектов Java , в основном они описывают создание реализации sizeof () в Java. Этот подход в основном основан на другой работе, в которой люди экспериментально определили размер примитивов и типичных объектов Java, а затем применили эти знания к методу, который рекурсивно просматривает граф объектов для подсчета общего размера.

Она всегда будет несколько менее точной, чем нативная реализация C, просто из-за того, что происходит за кулисами класса, но это должно быть хорошим индикатором.

В качестве альтернативы проект SourceForge, называемый соответствующим образом sizeof , предлагает библиотеку Java5 с реализацией sizeof ().

PS Не используйте подход сериализации, нет никакой корреляции между размером сериализованного объекта и объемом памяти, который он потребляет при работе.

74
9.09.2008 18:42:54
Утилита sizeof, вероятно, самая быстрая. Это в основном то, что сказал Стефан, но уже упакованный в банку, готовую к употреблению.
Alexandre L Telles 8.09.2009 22:42:50

java.lang.instrument.InstrumentationКласс обеспечивает хороший способ получить размер объекта Java, но он требует , чтобы определить premainи запустить программу с Java агентом. Это очень скучно, когда вам не нужен какой-либо агент, а затем вы должны предоставить фиктивный агент Jar для вашего приложения.

Таким образом, я получил альтернативное решение, используя Unsafeкласс из sun.misc. Таким образом, учитывая выравнивание кучи объектов в соответствии с архитектурой процессора и вычисляя максимальное смещение поля, вы можете измерить размер Java-объекта. В приведенном ниже примере я использую вспомогательный класс UtilUnsafeдля получения ссылки на sun.misc.Unsafeобъект.

private static final int NR_BITS = Integer.valueOf(System.getProperty("sun.arch.data.model"));
private static final int BYTE = 8;
private static final int WORD = NR_BITS/BYTE;
private static final int MIN_SIZE = 16; 

public static int sizeOf(Class src){
    //
    // Get the instance fields of src class
    // 
    List<Field> instanceFields = new LinkedList<Field>();
    do{
        if(src == Object.class) return MIN_SIZE;
        for (Field f : src.getDeclaredFields()) {
            if((f.getModifiers() & Modifier.STATIC) == 0){
                instanceFields.add(f);
            }
        }
        src = src.getSuperclass();
    }while(instanceFields.isEmpty());
    //
    // Get the field with the maximum offset
    //  
    long maxOffset = 0;
    for (Field f : instanceFields) {
        long offset = UtilUnsafe.UNSAFE.objectFieldOffset(f);
        if(offset > maxOffset) maxOffset = offset; 
    }
    return  (((int)maxOffset/WORD) + 1)*WORD; 
}
class UtilUnsafe {
    public static final sun.misc.Unsafe UNSAFE;

    static {
        Object theUnsafe = null;
        Exception exception = null;
        try {
            Class<?> uc = Class.forName("sun.misc.Unsafe");
            Field f = uc.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            theUnsafe = f.get(uc);
        } catch (Exception e) { exception = e; }
        UNSAFE = (sun.misc.Unsafe) theUnsafe;
        if (UNSAFE == null) throw new Error("Could not obtain access to sun.misc.Unsafe", exception);
    }
    private UtilUnsafe() { }
}
6
14.05.2012 16:37:13
Интересный подход, но разве это не предполагает, что хранилище объекта и его полей не фрагментировано?
nicoulaj 11.06.2012 13:25:47
Да, и я не знаю никакой реализации JVM, которая делает такую ​​фрагментацию.
Miguel Gamboa 18.06.2012 16:44:56
Я не понимаю Фрагментация не вариант :) Давайте рассмотрим пример объекта C, который хранится как поле объектов A и B. Разве это не сдвигает все это в A или B?
nicoulaj 19.06.2012 13:46:08
Извините, но я не понимаю вашу точку зрения. Согласно моей интерпретации, объекты Java не могут храниться внутри других объектов, как это происходит со структурами C или типами значений в .Net. Поэтому, когда вы говорите: «объект C, который хранится как поле объектов A и B», это означает, что у объектов A и B есть поля, в которых хранятся ссылки (указатели) на объект C. Тогда размеры A и B равны смещение этого поля плюс размер ссылки (указателя) на объект C. И размер ссылки равен размеру одного слова.
Miguel Gamboa 19.06.2012 14:24:34
О, хорошо, мы говорим о мелком размере. Виноват.
nicoulaj 19.06.2012 14:48:21

Вы можете сгенерировать дамп кучи (например, с помощью jmap), а затем проанализировать вывод, чтобы найти размеры объектов. Это автономное решение, но вы можете изучить мелкие и глубокие размеры и т. Д.

0
4.04.2013 15:08:07

Существует также инструмент Memory Measurer (ранее в Google Code , теперь в GitHub ), который прост и опубликован под коммерческой лицензией Apache 2.0 , как обсуждалось в аналогичном вопросе .

Он также требует аргумента командной строки для интерпретатора Java, если вы хотите измерить потребление памяти в байтах, но в остальном кажется, что он работает нормально, по крайней мере в тех сценариях, которые я использовал.

6
23.05.2017 12:34:36

Я написал быстрый тест один раз, чтобы оценить на лету:

public class Test1 {

    // non-static nested
    class Nested { }

    // static nested
    static class StaticNested { }

    static long getFreeMemory () {
        // waits for free memory measurement to stabilize
        long init = Runtime.getRuntime().freeMemory(), init2;
        int count = 0;
        do {
            System.out.println("waiting..." + init);
            System.gc();
            try { Thread.sleep(250); } catch (Exception x) { }
            init2 = init;
            init = Runtime.getRuntime().freeMemory();
            if (init == init2) ++ count; else count = 0;
        } while (count < 5);
        System.out.println("ok..." + init);
        return init;
    }

    Test1 () throws InterruptedException {

        Object[] s = new Object[10000];
        Object[] n = new Object[10000];
        Object[] t = new Object[10000];

        long init = getFreeMemory();

        //for (int j = 0; j < 10000; ++ j)
        //    s[j] = new Separate();

        long afters = getFreeMemory();

        for (int j = 0; j < 10000; ++ j)
            n[j] = new Nested();

        long aftersn = getFreeMemory();

        for (int j = 0; j < 10000; ++ j)
            t[j] = new StaticNested();

        long aftersnt = getFreeMemory();

        System.out.println("separate:      " + -(afters - init) + " each=" + -(afters - init) / 10000);
        System.out.println("nested:        " + -(aftersn - afters) + " each=" + -(aftersn - afters) / 10000);
        System.out.println("static nested: " + -(aftersnt - aftersn) + " each=" + -(aftersnt - aftersn) / 10000);

    }

    public static void main (String[] args) throws InterruptedException {
        new Test1();
    }

}

Общая концепция заключается в распределении объектов и измерении изменений в свободном пространстве кучи. Ключ getFreeMemory(), который запрашивает GC, запускается и ожидает стабилизации указанного размера свободной кучи . Результатом вышесказанного является:

nested:        160000 each=16
static nested: 160000 each=16

Что мы и ожидаем, учитывая поведение выравнивания и возможные издержки заголовка блока кучи.

Метод КИП, подробно изложенный в принятом ответе, здесь наиболее точен. Метод, который я описал, является точным, но только в контролируемых условиях, когда никакие другие потоки не создают / отбрасывают объекты.

2
16.11.2013 03:34:24
long heapSizeBefore = Runtime.getRuntime().totalMemory();

// Code for object construction
...
long heapSizeAfter = Runtime.getRuntime().totalMemory();
long size = heapSizeAfter - heapSizeBefore;

размер дает вам увеличение использования памяти jvm из-за создания объекта, и это, как правило, размер объекта.

0
7.05.2014 07:23:43
что если GC работает посередине во время // кода для построения объекта? Мог бы теперь дать правильный результат все время.
rajugaadu 17.06.2014 02:35:20

Вот утилита, которую я сделал, используя некоторые из связанных примеров для обработки 32-битных, 64-битных и 64-битных сжатых ООП. Это использует sun.misc.Unsafe.

Используется Unsafe.addressSize()для получения размера собственного указателя и Unsafe.arrayIndexScale( Object[].class )размера ссылки на Java.

Он использует смещение поля известного класса для определения базового размера объекта.

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Stack;
import sun.misc.Unsafe;

/** Usage: 
 * MemoryUtil.sizeOf( object )
 * MemoryUtil.deepSizeOf( object )
 * MemoryUtil.ADDRESS_MODE
 */
public class MemoryUtil
{
    private MemoryUtil()
    {
    }

    public static enum AddressMode
    {
        /** Unknown address mode. Size calculations may be unreliable. */
        UNKNOWN,
        /** 32-bit address mode using 32-bit references. */
        MEM_32BIT,
        /** 64-bit address mode using 64-bit references. */
        MEM_64BIT,
        /** 64-bit address mode using 32-bit compressed references. */
        MEM_64BIT_COMPRESSED_OOPS
    }

    /** The detected runtime address mode. */
    public static final AddressMode ADDRESS_MODE;

    private static final Unsafe UNSAFE;

    private static final long ADDRESS_SIZE; // The size in bytes of a native pointer: 4 for 32 bit, 8 for 64 bit
    private static final long REFERENCE_SIZE; // The size of a Java reference: 4 for 32 bit, 4 for 64 bit compressed oops, 8 for 64 bit
    private static final long OBJECT_BASE_SIZE; // The minimum size of an Object: 8 for 32 bit, 12 for 64 bit compressed oops, 16 for 64 bit
    private static final long OBJECT_ALIGNMENT = 8;

    /** Use the offset of a known field to determine the minimum size of an object. */
    private static final Object HELPER_OBJECT = new Object() { byte b; };


    static
    {
        try
        {
            // Use reflection to get a reference to the 'Unsafe' object.
            Field f = Unsafe.class.getDeclaredField( "theUnsafe" );
            f.setAccessible( true );
            UNSAFE = (Unsafe) f.get( null );

            OBJECT_BASE_SIZE = UNSAFE.objectFieldOffset( HELPER_OBJECT.getClass().getDeclaredField( "b" ) );

            ADDRESS_SIZE = UNSAFE.addressSize();
            REFERENCE_SIZE = UNSAFE.arrayIndexScale( Object[].class );

            if( ADDRESS_SIZE == 4 )
            {
                ADDRESS_MODE = AddressMode.MEM_32BIT;
            }
            else if( ADDRESS_SIZE == 8 && REFERENCE_SIZE == 8 )
            {
                ADDRESS_MODE = AddressMode.MEM_64BIT;
            }
            else if( ADDRESS_SIZE == 8 && REFERENCE_SIZE == 4 )
            {
                ADDRESS_MODE = AddressMode.MEM_64BIT_COMPRESSED_OOPS;
            }
            else
            {
                ADDRESS_MODE = AddressMode.UNKNOWN;
            }
        }
        catch( Exception e )
        {
            throw new Error( e );
        }
    }


    /** Return the size of the object excluding any referenced objects. */
    public static long shallowSizeOf( final Object object )
    {
        Class<?> objectClass = object.getClass();
        if( objectClass.isArray() )
        {
            // Array size is base offset + length * element size
            long size = UNSAFE.arrayBaseOffset( objectClass )
                    + UNSAFE.arrayIndexScale( objectClass ) * Array.getLength( object );
            return padSize( size );
        }
        else
        {
            // Object size is the largest field offset padded out to 8 bytes
            long size = OBJECT_BASE_SIZE;
            do
            {
                for( Field field : objectClass.getDeclaredFields() )
                {
                    if( (field.getModifiers() & Modifier.STATIC) == 0 )
                    {
                        long offset = UNSAFE.objectFieldOffset( field );
                        if( offset >= size )
                        {
                            size = offset + 1; // Field size is between 1 and PAD_SIZE bytes. Padding will round up to padding size.
                        }
                    }
                }
                objectClass = objectClass.getSuperclass();
            }
            while( objectClass != null );

            return padSize( size );
        }
    }


    private static final long padSize( final long size )
    {
        return (size + (OBJECT_ALIGNMENT - 1)) & ~(OBJECT_ALIGNMENT - 1);
    }


    /** Return the size of the object including any referenced objects. */
    public static long deepSizeOf( final Object object )
    {
        IdentityHashMap<Object,Object> visited = new IdentityHashMap<Object,Object>();
        Stack<Object> stack = new Stack<Object>();
        if( object != null ) stack.push( object );

        long size = 0;
        while( !stack.isEmpty() )
        {
            size += internalSizeOf( stack.pop(), stack, visited );
        }
        return size;
    }


    private static long internalSizeOf( final Object object, final Stack<Object> stack, final IdentityHashMap<Object,Object> visited )
    {
        // Scan for object references and add to stack
        Class<?> c = object.getClass();
        if( c.isArray() && !c.getComponentType().isPrimitive() )
        {
            // Add unseen array elements to stack
            for( int i = Array.getLength( object ) - 1; i >= 0; i-- )
            {
                Object val = Array.get( object, i );
                if( val != null && visited.put( val, val ) == null )
                {
                    stack.add( val );
                }
            }
        }
        else
        {
            // Add unseen object references to the stack
            for( ; c != null; c = c.getSuperclass() )
            {
                for( Field field : c.getDeclaredFields() )
                {
                    if( (field.getModifiers() & Modifier.STATIC) == 0 
                            && !field.getType().isPrimitive() )
                    {
                        field.setAccessible( true );
                        try
                        {
                            Object val = field.get( object );
                            if( val != null && visited.put( val, val ) == null )
                            {
                                stack.add( val );
                            }
                        }
                        catch( IllegalArgumentException e )
                        {
                            throw new RuntimeException( e );
                        }
                        catch( IllegalAccessException e )
                        {
                            throw new RuntimeException( e );
                        }
                    }
                }
            }
        }

        return shallowSizeOf( object );
    }
}
3
26.06.2014 06:02:35
Вы проверяли этот класс со значениями? Я пытался, но для меня неверные значения !!!.
Débora 17.08.2014 14:26:49
Значения, которые он дал мне для простого объекта, были примерно правильными, но с коэффициентом 10 для списка, содержащего 1 миллион объектов. Тем не менее, очень хорошая работа!
Michael Böckling 21.08.2014 13:12:46
Интересно. Я протестировал его, используя JDK7u67, в Windows 7 x64 и Linux 2.6.16 / x86_64, используя каждый из 32-битных / 64-битных / oop режимов адресации. Я сравнил это с дампами памяти, проанализированными в Eclipse Memory Analyzer 1.3.x. Какие настройки вы используете? У вас есть конкретный пример, который я мог бы попробовать?
dlaudams 9.09.2014 05:43:03
Лучший выбор, который я могу сделать. Я не могу использовать, Instrumentationпотому что я не запускаю tomcat, ObjectSizeCalculatorпотому что не уверен в типе VM (HotSpot) и JOLбобовых весенних бобах. Я использую это и добавляю второй параметр для игнорирования синглетонов, а именно код AbstractRefreshableApplicationContext.getBeanFactory().getSingletonMutex()рефакторинга, internalSizeOfчтобы игнорировать Class и Enum
Perlos 14.09.2018 12:56:18
Для сравнения результатов используйте ObjectSizeCalculator (вычислить весь сервер от 1 ГБ до 10 с). JOL вызывает MemError (6GB не должно быть достаточно), и я не получаю те же результаты, вероятно, потому что перечисления.
Perlos 14.09.2018 13:08:47

Мой ответ основан на коде, предоставленном Ником. Этот код измеряет общее количество байтов, которые заняты сериализованным объектом. Так что это фактически измеряет материал сериализации + объем памяти простого объекта (просто сериализуйте, например, intи вы увидите, что общее количество сериализованных байтов не так 4). Поэтому, если вы хотите получить необработанный номер байта, используемый именно для вашего объекта - вам нужно немного изменить этот код. Вот так:

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectSizeCalculator {
    private Object getFirstObjectReference(Object o) {
        String objectType = o.getClass().getTypeName();

        if (objectType.substring(objectType.length()-2).equals("[]")) {
            try {
                if (objectType.equals("java.lang.Object[]"))
                    return ((Object[])o)[0];
                else if (objectType.equals("int[]"))
                    return ((int[])o)[0];
                else
                    throw new RuntimeException("Not Implemented !");
            } catch (IndexOutOfBoundsException e) {
                return null;
            }
        }

        return o;
    } 

    public int getObjectSizeInBytes(Object o) {
        final String STRING_JAVA_TYPE_NAME = "java.lang.String";

        if (o == null)
            return 0;

        String objectType = o.getClass().getTypeName();
        boolean isArray = objectType.substring(objectType.length()-2).equals("[]");

        Object objRef = getFirstObjectReference(o);
        if (objRef != null && !(objRef instanceof Serializable))
            throw new RuntimeException("Object must be serializable for measuring it's memory footprint using this method !");

        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(o);
            oos.close();
            byte[] bytes = baos.toByteArray();

            for (int i = bytes.length - 1, j = 0; i != 0; i--, j++) {
                if (objectType != STRING_JAVA_TYPE_NAME) {
                    if (bytes[i] == 112)
                        if (isArray)
                            return j - 4;
                        else
                            return j;
                } else {
                    if (bytes[i] == 0)
                        return j - 1;
                }
            }
        } catch (Exception e) {
            return -1;
        }

        return -1;
    }    

}

Я протестировал это решение с примитивными типами, String и на некоторых тривиальных классах. Также могут быть не охваченные случаи.


ОБНОВЛЕНИЕ: Пример изменен для поддержки вычисления объема памяти для объектов массива.

1
19.10.2014 21:53:42

Этот ответ не относится к размеру объекта, но когда вы используете массив для размещения объектов; какой объем памяти он выделит для объекта.

Таким образом, массивы, списки или карты всей этой коллекции не будут на самом деле хранить объекты (только во время примитивов, необходим реальный объем памяти объекта), он будет хранить только ссылки на эти объекты.

Теперь Used heap memory = sizeOfObj + sizeOfRef (* 4 bytes) in collection

  • (4/8 байт) зависит от (32/64 бит) ОС

примитивов

int   [] intArray    = new int   [1]; will require 4 bytes.
long  [] longArray   = new long  [1]; will require 8 bytes.

ОБЪЕКТЫ

Object[] objectArray = new Object[1]; will require 4 bytes. The object can be any user defined Object.
Long  [] longArray   = new Long  [1]; will require 4 bytes.

Я имею в виду, что весь объект REFERENCE требует только 4 байта памяти. Это может быть ссылка на строку ИЛИ двойная ссылка на объект, но в зависимости от создания объекта необходимая память будет варьироваться.

Например, если я создаю объект для класса ниже, ReferenceMemoryTestто будет создано 4 + 4 + 4 = 12 байт памяти. Память может отличаться, когда вы пытаетесь инициализировать ссылки.

 class ReferenceMemoryTest {
    public String refStr;
    public Object refObj;
    public Double refDoub; 
}

Поэтому, когда вы создаете массив объектов / ссылок, все его содержимое будет занято пустыми ссылками. И мы знаем, что каждая ссылка требует 4 байта.

И, наконец, выделение памяти для приведенного ниже кода составляет 20 байтов.

ReferenceMemoryTest ref1 = new ReferenceMemoryTest (); (4 (ref1) + 12 = 16 байт) ReferenceMemoryTest ref2 = ref1; (4 (ref2) + 16 = 20 байт)

0
13.07.2015 03:32:51
Как может 4-байтовое целое число и ссылка на объект неизвестного размера вписаться в 4 байта?
user207421 4.05.2015 01:14:35
@EJP Я имею в виду, что весь объект REFERENCE требует только 4 байта памяти. Это может быть ссылка на строку ИЛИ двойная ссылка на объект, но в зависимости от создания объекта необходимая память будет варьироваться.
Kanagavelu Sugumar 4.05.2015 04:50:06

Большая часть других ответов предоставляет небольшие размеры - например, размер HashMap без каких-либо ключей или значений, что, скорее всего, не то, что вам нужно.

Проект jamm использует пакет java.lang.instrumentation выше, но обходит дерево и поэтому может дать вам глубокое использование памяти.

new MemoryMeter().measureDeep(myHashMap);

https://github.com/jbellis/jamm

Чтобы использовать MemoryMeter, запустите JVM с "-javaagent: /jamm.jar"

17
9.06.2019 00:24:50

Без необходимости возиться с инструментарием и т. Д., И если вам не нужно знать точный размер объекта в байтах, вы можете использовать следующий подход:

System.gc();
Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

do your job here

System.gc();
Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

Таким образом, вы читаете использованную память до и после, и, вызывая GC непосредственно перед получением использованной памяти, вы понижаете «шум» почти до 0.

Для более надежного результата вы можете выполнить свою работу n раз, а затем разделить использованную память на n, получив, сколько памяти занимает один запуск. Более того, вы можете запустить все это больше раз и получить среднее значение.

3
3.04.2015 12:09:59
Разве не System.gc()просто уведомить, что вы хотите GC? Не гарантируется, что GC вызывается вообще.
Raildex 11.01.2017 13:42:59
@действительно мило. Это небезопасно, потому что вы можете никогда не делать то, что GC делает или влияет на память между вашими строками. Таким образом, «между» двумя методами freeMemory GC может высвободить больше места, которое вы не считаете, таким образом, ваш объект будет выглядеть меньше
Mert Serimer 14.12.2017 10:37:28
@MertSerimer «небезопасно» для меня на совершенно другом уровне: в большинстве случаев это не так точно, как я также говорил. Кроме того, вы не можете управлять GC (как заявлено Raildex), но и для этого случая я предложил вставить это в цикл. Это просто быстрая и грязная и приблизительная система, которая работает, если результат не должен быть очень надежным, как указано.
reallynice 14.12.2017 14:34:56

Еще когда я работал в Twitter, я написал утилиту для расчета глубокого размера объекта. Он учитывает различные модели памяти (32-разрядные, сжатые операции, 64-разрядные), заполнение, заполнение подклассов, корректно работает с циклическими структурами данных и массивами. Вы можете просто скомпилировать этот файл .java; у него нет внешних зависимостей:

https://github.com/twitter/commons/blob/master/src/java/com/twitter/common/objectsize/ObjectSizeCalculator.java

23
9.04.2015 11:07:01
Szia! Я также хотел бы выкрикнуть и вашу презентацию : слайды 15–20 великолепно помогают инстинктивно ощутить стоимость различных решений по структуре данных. Спасибо за публикацию этого!
Luke Usherwood 1.10.2015 01:58:14
«у него нет внешних зависимостей» - с каких пор гуава не является внешней зависимостью?
l4mpi 11.01.2016 14:21:44
выглядит очень похоже на github.com/JetBrains/jdk8u_nashorn/blob/master/src/jdk/nashorn/… ? : O
Francesco 24.10.2017 14:02:15
Guave - это внешняя зависимость.
Mert Serimer 14.12.2017 10:33:36

Вам следует использовать jol , инструмент, разработанный как часть проекта OpenJDK.

JOL (Java Object Layout) - это крошечный набор инструментов для анализа схем компоновки объектов в JVM. Эти инструменты в значительной степени используют Unsafe, JVMTI и Serviceability Agent (SA) для декодирования фактического макета объекта, площади и ссылок. Это делает JOL намного более точным, чем другие инструменты, основанные на дампах кучи, допущениях спецификации и т. Д.

Чтобы получить размеры примитивов, ссылок и элементов массива, используйте VMSupport.vmDetails(). В Oracle JDK 1.8.0_40, работающем в 64-битной Windows (используется для всех следующих примеров), этот метод возвращает

Running 64-bit HotSpot VM.
Using compressed oop with 0-bit shift.
Using compressed klass with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

Вы можете получить небольшой размер экземпляра объекта, используя ClassLayout.parseClass(Foo.class).toPrintable()(опционально передавая экземпляр toPrintable). Это только пространство, занимаемое одним экземпляром этого класса; он не включает никаких других объектов, на которые ссылается этот класс. Он включает в себя служебные данные VM для заголовка объекта, выравнивания полей и заполнения. Для java.util.regex.Pattern:

java.util.regex.Pattern object internals:
 OFFSET  SIZE        TYPE DESCRIPTION                    VALUE
      0     4             (object header)                01 00 00 00 (0000 0001 0000 0000 0000 0000 0000 0000)
      4     4             (object header)                00 00 00 00 (0000 0000 0000 0000 0000 0000 0000 0000)
      8     4             (object header)                cb cf 00 20 (1100 1011 1100 1111 0000 0000 0010 0000)
     12     4         int Pattern.flags                  0
     16     4         int Pattern.capturingGroupCount    1
     20     4         int Pattern.localCount             0
     24     4         int Pattern.cursor                 48
     28     4         int Pattern.patternLength          0
     32     1     boolean Pattern.compiled               true
     33     1     boolean Pattern.hasSupplementary       false
     34     2             (alignment/padding gap)        N/A
     36     4      String Pattern.pattern                (object)
     40     4      String Pattern.normalizedPattern      (object)
     44     4        Node Pattern.root                   (object)
     48     4        Node Pattern.matchRoot              (object)
     52     4       int[] Pattern.buffer                 null
     56     4         Map Pattern.namedGroups            null
     60     4 GroupHead[] Pattern.groupNodes             null
     64     4       int[] Pattern.temp                   null
     68     4             (loss due to the next object alignment)
Instance size: 72 bytes (reported by Instrumentation API)
Space losses: 2 bytes internal + 4 bytes external = 6 bytes total

Вы можете получить сводный вид глубинного размера экземпляра объекта, используя GraphLayout.parseInstance(obj).toFootprint(). Конечно, некоторые объекты в элементе footprint могут быть общими (также на них ссылаются другие объекты), так что это избыточное приближение пространства, которое можно восстановить, когда этот объект собирается мусором. Для результата Pattern.compile("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$")(взятого из этого ответа ) jol сообщает об общем размере 1840 байт, из которых только 72 являются самим экземпляром Pattern.

java.util.regex.Pattern instance footprint:
     COUNT       AVG       SUM   DESCRIPTION
         1       112       112   [C
         3       272       816   [Z
         1        24        24   java.lang.String
         1        72        72   java.util.regex.Pattern
         9        24       216   java.util.regex.Pattern$1
        13        24       312   java.util.regex.Pattern$5
         1        16        16   java.util.regex.Pattern$Begin
         3        24        72   java.util.regex.Pattern$BitClass
         3        32        96   java.util.regex.Pattern$Curly
         1        24        24   java.util.regex.Pattern$Dollar
         1        16        16   java.util.regex.Pattern$LastNode
         1        16        16   java.util.regex.Pattern$Node
         2        24        48   java.util.regex.Pattern$Single
        40                1840   (total)

Если вы вместо этого используете GraphLayout.parseInstance(obj).toPrintable(), jol сообщит вам адрес, размер, тип, значение и путь разыменования полей к каждому объекту, на который ссылаются, хотя обычно это слишком много деталей, чтобы быть полезным. Для текущего примера шаблона вы можете получить следующее. (Адреса, вероятно, будут меняться между пробегами.)

java.util.regex.Pattern object externals:
          ADDRESS       SIZE TYPE                             PATH                           VALUE
         d5e5f290         16 java.util.regex.Pattern$Node     .root.next.atom.next           (object)
         d5e5f2a0        120 (something else)                 (somewhere else)               (something else)
         d5e5f318         16 java.util.regex.Pattern$LastNode .root.next.next.next.next.next.next.next (object)
         d5e5f328      21664 (something else)                 (somewhere else)               (something else)
         d5e647c8         24 java.lang.String                 .pattern                       (object)
         d5e647e0        112 [C                               .pattern.value                 [^, [, a, -, z, A, -, Z, 0, -, 9, _, ., +, -, ], +, @, [, a, -, z, A, -, Z, 0, -, 9, -, ], +, \, ., [, a, -, z, A, -, Z, 0, -, 9, -, ., ], +, $]
         d5e64850        448 (something else)                 (somewhere else)               (something else)
         d5e64a10         72 java.util.regex.Pattern                                         (object)
         d5e64a58        416 (something else)                 (somewhere else)               (something else)
         d5e64bf8         16 java.util.regex.Pattern$Begin    .root                          (object)
         d5e64c08         24 java.util.regex.Pattern$BitClass .root.next.atom.val$rhs        (object)
         d5e64c20        272 [Z                               .root.next.atom.val$rhs.bits   [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
         d5e64d30         24 java.util.regex.Pattern$1        .root.next.atom.val$lhs.val$lhs.val$lhs.val$lhs.val$lhs.val$lhs (object)
         d5e64d48         24 java.util.regex.Pattern$1        .root.next.atom.val$lhs.val$lhs.val$lhs.val$lhs.val$lhs.val$rhs (object)
         d5e64d60         24 java.util.regex.Pattern$5        .root.next.atom.val$lhs.val$lhs.val$lhs.val$lhs.val$lhs (object)
         d5e64d78         24 java.util.regex.Pattern$1        .root.next.atom.val$lhs.val$lhs.val$lhs.val$lhs.val$rhs (object)
         d5e64d90         24 java.util.regex.Pattern$5        .root.next.atom.val$lhs.val$lhs.val$lhs.val$lhs (object)
         d5e64da8         24 java.util.regex.Pattern$5        .root.next.atom.val$lhs.val$lhs.val$lhs (object)
         d5e64dc0         24 java.util.regex.Pattern$5        .root.next.atom.val$lhs.val$lhs (object)
         d5e64dd8         24 java.util.regex.Pattern$5        .root.next.atom.val$lhs        (object)
         d5e64df0         24 java.util.regex.Pattern$5        .root.next.atom                (object)
         d5e64e08         32 java.util.regex.Pattern$Curly    .root.next                     (object)
         d5e64e28         24 java.util.regex.Pattern$Single   .root.next.next                (object)
         d5e64e40         24 java.util.regex.Pattern$BitClass .root.next.next.next.atom.val$rhs (object)
         d5e64e58        272 [Z                               .root.next.next.next.atom.val$rhs.bits [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, fal
113
4.05.2015 00:46:52
Этот ответ должен иметь больше голосов. Определенно очень хороший вариант для проверки. РЕДАКТИРОВАТЬ: Проверено, что это было добавлено в этом году, в то время как вопрос был задан в '08. Вероятно, лучший и самый простой вариант сделать то, что ОП спросил в данный момент.
rents 30.08.2015 19:22:06
Автор инструмента написал пост в блоге о Джол .
Mike 6.09.2015 00:37:28
Чтобы определить размер объекта "obj" используйте: org.openjdk.jol.info.GraphLayout.parseInstance (obj) .totalSize ();
vigor 19.01.2017 09:26:55
Обратите внимание, что vmDetailsсейчас VM.current().details().
Miha_x64 13.05.2018 07:35:25
Посмотрите, GraphLayout.parseInstance(instance).toFootprint()я нашел более полезным для понимания размеров объектов
Mugen 2.04.2020 08:37:38

Я случайно нашел java-класс "jdk.nashorn.internal.ir.debug.ObjectSizeCalculator", уже в jdk, который прост в использовании и кажется весьма полезным для определения размера объекта.

System.out.println(ObjectSizeCalculator.getObjectSize(new gnu.trove.map.hash.TObjectIntHashMap<String>(12000, 0.6f, -1)));
System.out.println(ObjectSizeCalculator.getObjectSize(new HashMap<String, Integer>(100000)));
System.out.println(ObjectSizeCalculator.getObjectSize(3));
System.out.println(ObjectSizeCalculator.getObjectSize(new int[]{1, 2, 3, 4, 5, 6, 7 }));
System.out.println(ObjectSizeCalculator.getObjectSize(new int[100]));

полученные результаты:

164192
48
16
48
416
77
9.09.2016 07:53:20
Здесь я попробовал другие решения, предложенные выше, и наткнулся на ObjectSizeCalculator. Я полагаю, никто не упомянул, если раньше, так как он был недавно представлен на JDK 8 в рамках проекта Nashorn . Однако я не нашел официальной документации об этом классе в Интернете.
Henrique Gontijo 16.10.2016 18:26:32
Кажется, он не учитывает длины строк. Это просто размер в стеке?
jontejj 7.05.2017 08:50:24
У меня есть хэш-карта, где com.carrotsearch.RamUsageEstimator возвращает около половины ObjectSizeCalculator. Какой из них является правдой? - Какой из них более надежный?
badera 18.05.2017 08:36:58
Обратите внимание, что ObjectSizeCalculatorподдерживается только на HotSpot VM
kellanburket 2.02.2018 21:04:23

Для JSONObject вам может помочь приведенный ниже код.

`JSONObject.toString().getBytes("UTF-8").length`

возвращает размер в байтах

Я проверил это с моим объектом JSONArray, записав его в файл. Это дает размер объекта.

-4
1.08.2018 15:56:11
это будет работать только для объектов, которые в основном являются строками.
Dexter Legaspi 7.05.2018 21:12:11

Просто используйте Java Visual VM.

В нем есть все необходимое для профилирования и устранения проблем с памятью.

Он также имеет консоль OQL (Object Query Language), которая позволяет вам делать много полезных вещей, одним из которых является sizeof(o)

2
23.03.2018 11:53:26

Предположим, я объявил класс с именем Complexвроде:

public class Complex {

    private final long real;
    private final long imaginary;

    // omitted
}

Чтобы увидеть, сколько памяти выделено для живых экземпляров этого класса:

$ jmap -histo:live <pid> | grep Complex

 num     #instances         #bytes  class name (module)
-------------------------------------------------------
 327:             1             32  Complex
0
28.03.2019 17:58:23

Я искал во время выполнения вычисления размера объекта, который удовлетворял бы следующим требованиям:

  • Доступно во время выполнения без необходимости включать инструментарий.
  • Работает с Java 9+ без доступа к Unsafe.
  • Основан только на классе. Не глубокий sizeOf, который учитывает длину строки, длину массива и т. Д.

Нижеследующее основано на основном коде исходной статьи специалистов по Java ( https://www.javaspecialists.eu/archive/Issue078.html ) и нескольких фрагментах небезопасной версии в другом ответе на этот вопрос.

Я надеюсь, что кто-то найдет это полезным.

public class JavaSize {

private static final int NR_BITS = Integer.valueOf(System.getProperty("sun.arch.data.model"));
private static final int BYTE = 8;
private static final int WORD = NR_BITS / BYTE;
private static final int HEADER_SIZE = 8;

public static int sizeOf(Class<?> clazz) {
    int result = 0;

    while (clazz != null) {
        Field[] fields = clazz.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            if (!Modifier.isStatic(fields[i].getModifiers())) {
                if (fields[i].getType().isPrimitive()) {
                    Class<?> primitiveClass = fields[i].getType();
                    if (primitiveClass == boolean.class || primitiveClass == byte.class) {
                        result += 1;
                    } else if (primitiveClass == short.class) {
                        result += 2;
                    } else if (primitiveClass == int.class || primitiveClass == float.class) {
                        result += 4;
                    } else if (primitiveClass == double.class || primitiveClass == long.class) {
                        result += 8;
                    }

                } else {
                    // assume compressed references.
                    result += 4;
                }
            }
        }

        clazz = clazz.getSuperclass();

        // round up to the nearest WORD length.
        if ((result % WORD) != 0) {
            result += WORD - (result % WORD);
        }
    }

    result += HEADER_SIZE;

    return result;
}

}

3
27.06.2019 04:40:10