Подтвердить что ты не робот

Java: размер внутреннего класса

У меня есть этот класс:

public class Stack {

   private class Node {
       String item;
       Node next;
   }
   // some other methods here

}

В моей книге автор говорит, что размер в стеке Node равен 40 байтам, включая:

16 bytes (object overhead)
8 bytes (inner class extra overhead)
8 bytes (references to string)
8 bytes (references to node)
----------------------------------------------
40 bytes per stack node

Я понимаю, что последние две вещи относятся к размеру ссылок на String и Node. Но я не знаю, что соответствуют object overhead и inner class extra overhead. Не могли бы вы объяснить?

4b9b3361

Ответ 1

накладные расходы

Каждый объект имеет заголовок, который обычно имеет длину 8-12 байтов. Каждый объект также выровнен по 8 байт, а простая оценка - это примерно 16 байтов.

дополнительные служебные расходы класса

Поскольку ваш внутренний класс не является статичным, он ссылается на внешний класс.

Если это был анонимный внутренний класс, у вас могут быть копии любого количества конечных переменных (любые, используемые в коде анонимного класса)

8 байтов (дополнительные служебные данные для внутреннего класса) 8 байтов (ссылки на строку) 8 байтов (ссылки на node)

Большинство JVM используют 32-битные ссылки, поэтому размер будет 4 байта. Даже 64-битная JVM с кучей до 32 ГБ может использовать 32-битные ссылки.

Ответ 2

Прежде всего: все конкретные цифры, которые вы цитируете, очень зависимы от реализации и могут сильно варьироваться в зависимости от того, какую JVM вы используете.

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

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

То, что вы называете дополнительными служебными данными внутреннего класса, вероятно, относится к тому факту, что каждый экземпляр нестатического внутреннего класса "привязан" к экземпляру внешнего класса. Вы можете думать о нем как о неявном поле, которое выглядит так: private final Stack Stack_this. Фактически, вы можете фактически использовать это значение, обратившись к Stack.this внутри кода Node. Это поле implcit будет занимать тот же объем памяти, что и нормальная ссылочная переменная (обычно это 4 или 8 байт, в зависимости от вашей архитектуры/JVM).

Ответ 3

Здесь вы можете найти ответ: Каковы издержки памяти для объекта в Java?

И более подробный ответ здесь:

Использование памяти объектов в Java: http://www.javamex.com/tutorials/memory/object_memory_usage.shtml

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

Ответ 4

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

Ответ 5

Внутренний класс имеет неявную ссылку на внешний класс, как если бы он имел объект Stack outer, который инициализируется в конструкторе. Эта ссылка - это то, что потребляет дополнительные 8 байтов, и именно это позволяет использовать Stack.this в вашем внутреннем классе. Вот пример фрагмента:

public class Stack {
    String item;   // intentionally named the same as the one in the inner class

    private class Node {
        String item; // hides the field in the outer class!
        Node next;

        void doSomething() {
            this.item = null;
            Stack.this.item = null; // << note the reference to the outer instance
        }
    }
}

Обратите внимание, что внутренний класс static не несет накладных расходов, поскольку он не имеет указателя на внешний объект.

Ответ 6

Точный размер любого конкретного объекта конкретно не определен в любая спецификация платформы Java

Количество служебных данных, связанных с объектом, не определено, но 8 байты типичны.

Подробнее см. здесь

Ответ 7

Во-первых, ваши значения для ссылок на объекты предполагают 64-разрядную JVM, на 32-битной JVM, ссылки используют 4 байта.

Накладные расходы объекта - это заголовок объекта, который содержит информацию об объекте, используемую JVM и обычно составляет 16 байтов.

Внутренний класс над головой связан с тем, что внутренний класс содержит ссылку на содержащий объект (экземпляр Stack).

Ответ 8

Я до сих пор не понимаю, как "40 байт в стеке node" означает. Вы знаете, когда я создаю новый экземпляр Node, я не создаю новый экземпляр Stack. Как я могу взять 16 байтов (накладные расходы объекта) во время создания нового экземпляра Node? Я тоже следую Алгоритму, и я был здесь замешан.