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
. Не могли бы вы объяснить?
Ответы
Ответ 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? Я тоже следую Алгоритму, и я был здесь замешан.