



Нет, для регистрации объекта тоже требуется немного памяти. 100 объектов с 1 атрибутом займут больше памяти.
нет, 100 маленьких объектов требует больше информации (памяти), чем один большой.
У каждого объекта есть определенные накладные расходы на связанный с ним монитор и информацию о типе, а также на сами поля. Помимо этого, поля могут быть размещены практически так, как JVM считает нужным (я считаю), но, поскольку показано в другом ответе, по крайней мере, немного JVM будут упакованы довольно плотно. Рассмотрим такой класс:
public class SingleByte
{
private byte b;
}
против
public class OneHundredBytes
{
private byte b00, b01, ..., b99;
}
На 32-битной JVM я ожидаю, что 100 экземпляров SingleByte займут 1200 байтов (8 байтов служебных + 4 байта для поля из-за заполнения / выравнивания). Я ожидал, что один экземпляр OneHundredBytes займет 108 байтов - служебные данные, а затем 100 байтов в упаковке. Это, безусловно, может варьироваться в зависимости от JVM - одна реализация может решить не упаковывать поля в OneHundredBytes, что приведет к тому, что она займет 408 байтов (= 8 байтов накладных расходов + 4 * 100 выровненных / дополненных байтов). На 64-битной JVM накладные расходы тоже могут быть больше (не уверен).
Обновлено: см. Комментарий ниже; очевидно, HotSpot ограничивает границы 8 байтами вместо 32, поэтому каждый экземпляр SingleByte будет занимать 16 байтов.
В любом случае «один большой объект» будет по крайней мере так же эффективен, как несколько небольших объектов - для таких простых случаев, как этот.
Mindprod указывает, что на этот вопрос непросто ответить:
A JVM is free to store data any way it pleases internally, big or little endian, with any amount of padding or overhead, though primitives must behave as if they had the official sizes.
For example, the JVM or native compiler might decide to store aboolean[]in 64-bit long chunks like aBitSet. It does not have to tell you, so long as the program gives the same answers.
- It might allocate some temporary Objects on the stack.
- It may optimize some variables or method calls totally out of existence replacing them with constants.
- It might version methods or loops, i.e. compile two versions of a method, each optimized for a certain situation, then decide up front which one to call.
Then of course the hardware and OS have multilayer caches, on chip-cache, SRAM cache, DRAM cache, ordinary RAM working set and backing store on disk. Your data may be duplicated at every cache level. All this complexity means you can only very roughly predict RAM consumption.
Вы можете использовать Instrumentation.getObjectSize(), чтобы получить оценку хранилища, потребляемого объектом.
Для визуализации компоновки, посадочного места и ссылок объекта действительный можно использовать Инструмент JOL (Java Object Layout).
В современном 64-битном JDK объект имеет 12-байтовый заголовок, дополненный кратным 8 байтам, поэтому минимальный размер объекта составляет 16 байтов. Для 32-битных JVM накладные расходы составляют 8 байтов с дополнениями, кратными 4 байтам. (Из Ответ Дмитрия Спихальского, Ответ Джейен и JavaWorld.)
Обычно ссылки составляют 4 байта на 32-битных платформах или на 64-битных платформах вплоть до -Xmx32G; и 8 байтов выше 32 ГБ (-Xmx32G). (См. ссылки на сжатые объекты.)
В результате 64-битной JVM обычно требуется на 30-50% больше места в куче. (Что мне следует использовать: 32- или 64-битную JVM?, 2012, JDK 1.7)
Упакованные обертки имеют накладные расходы по сравнению с примитивными типами (из JavaWorld):
Integer: The 16-byte result is a little worse than I expected because anintvalue can fit into just 4 extra bytes. Using anIntegercosts me a 300 percent memory overhead compared to when I can store the value as a primitive type
Long: 16 bytes also: Clearly, actual object size on the heap is subject to low-level memory alignment done by a particular JVM implementation for a particular CPU type. It looks like aLongis 8 bytes of Object overhead, plus 8 bytes more for the actual long value. In contrast,Integerhad an unused 4-byte hole, most likely because the JVM I use forces object alignment on an 8-byte word boundary.
Дорого стоят и другие контейнеры:
Multidimensional arrays: it offers another surprise.
Developers commonly employ constructs likeint[dim1][dim2]in numerical and scientific computing.In an
int[dim1][dim2]array instance, every nestedint[dim2]array is anObjectin its own right. Each adds the usual 16-byte array overhead. When I don't need a triangular or ragged array, that represents pure overhead. The impact grows when array dimensions greatly differ.For example, a
int[128][2]instance takes 3,600 bytes. Compared to the 1,040 bytes anint[256]instance uses (which has the same capacity), 3,600 bytes represent a 246 percent overhead. In the extreme case ofbyte[256][1], the overhead factor is almost 19! Compare that to the C/C++ situation in which the same syntax does not add any storage overhead.
String: aString's memory growth tracks its internal char array's growth. However, theStringclass adds another 24 bytes of overhead.For a nonempty
Stringof size 10 characters or less, the added overhead cost relative to useful payload (2 bytes for each char plus 4 bytes for the length), ranges from 100 to 400 percent.
Рассмотрим этот пример объекта:
class X { // 8 bytes for reference to the class definition
int a; // 4 bytes
byte b; // 1 byte
Integer c = new Integer(); // 4 bytes for a reference
}
Наивная сумма предполагает, что экземпляр X будет использовать 17 байтов. Однако из-за выравнивания (также называемого заполнением) JVM выделяет память в количестве, кратном 8 байтам, поэтому вместо 17 байтов она будет выделять 24 байта.
int [128] [6]: 128 массивов из 6 целых чисел - всего 768 байтов, 3072 байта данных + 2064 байта Накладные расходы на объект = всего 5166 байтов. int [256]: всего 256 int - поэтому несопоставимо. int [768]: 3072 байта данных + 16 байтов накладных расходов - примерно 3/5 пространства 2D-массива - не совсем 246% накладных расходов!
Ах, в исходной статье использовалось int [128] [2], а не int [128] [6] - интересно, как это изменилось. Также показывает, что крайние примеры могут рассказать другую историю.
@Jeebee: я исправил опечатки. int [128] [2] стал int [128] [6] из-за ошибки в редакторе Javascript: ссылки указываются с помощью [aTest] [x], и редактор принял [128] [2] как адрес ссылки ! Он «переупорядочил» индексы этих ссылок, изменив [2] на [6] ... сложно!
Накладные расходы составляют 16 байт в 64-битной JVM.
@TimCooper Нет! Накладные расходы (= new Object ()) 64-битной Sun VM Java 1.6, работающей на 64-битной Win7, Intel составляют 12 байтов + 4 отступа до следующего числа, кратного 8, составляют 16 байтов. Итак, если у вас есть объект с одним полем int, это все равно 16 байтов. (без отступов)
@AlexWien: Некоторые схемы сборки мусора могут устанавливать минимальный размер объекта, отдельный от заполнения. Во время сборки мусора, как только объект копируется из старого местоположения в новое, старое местоположение может больше не хранить данные для объекта, но оно должно будет содержать ссылку на новое местоположение; может также потребоваться сохранить ссылку на старое местоположение объекта, в котором была обнаружена первая ссылка, и смещение этой ссылки в старом объекте [поскольку старый объект может все еще содержать ссылки, которые еще не были обработаны].
@AlexWien: использование памяти в старом местоположении объекта для хранения бухгалтерской информации сборщика мусора позволяет избежать необходимости выделять для этой цели другую память, но может потребовать минимального размера объекта, который больше, чем требовалось бы в противном случае. Я думаю, что по крайней мере одна версия сборщика мусора .NET использует этот подход; Конечно, некоторые сборщики мусора Java тоже могли бы поступить так же.
@VonC Этот ответ устарел, потому что в наши дни многие люди используют 64-битные JVM, и ваш ответ фактически игнорирует 64-битные JVM. Хорошо сказать «ну, это зависит от ...», но также полезно дать несколько хороших практических советов - вещей, которые верны для 99% JVM, таких как «8 байтов для 32-битных, 12 байтов + 8-байтовое выравнивание. для 64 бит, плюс указатели на 8 байт выше -Xmx32G ".
Я получил очень хорошие результаты от подхода java.lang.instrument.Instrumentation, упомянутого в другом ответе. Хорошие примеры его использования см. В статье Счетчик памяти КИП из Информационного бюллетеня JavaSpecialists и библиотеки java.sizeOf на SourceForge.
Правила о том, сколько памяти потребляется, зависят от реализации JVM и архитектуры ЦП (например, 32-разрядная версия вместо 64-разрядной).
Чтобы узнать подробные правила для SUN JVM, проверьте мой старый блог
С уважением, Маркус
Я почти уверен, что Sun Java 1.6 64bit, нужно 12 байтов для простого объекта + 4 отступа = 16; Объект + одно целочисленное поле = 12 + 4 = 16
Вы закрыли свой блог?
Не совсем. Не уверен, что блоги SAP каким-то образом переместились. Большинство из них можно найти здесь kohlerm.blogspot.com
Если это кому-то будет полезно, вы можете скачать с моего сайта небольшой Агент Java для запроса использования памяти объектом. Это также позволит вам запрашивать "глубокое" использование памяти.
Это отлично сработало для получения приблизительной оценки того, сколько памяти использует (String, Integer) Guava Cache для каждого элемента. Спасибо!
Общий объем используемой / свободной памяти программы можно получить в программе через
java.lang.Runtime.getRuntime();
Среда выполнения имеет несколько методов, связанных с памятью. Следующий пример кодирования демонстрирует его использование.
public class PerformanceTest {
private static final long MEGABYTE = 1024L * 1024L;
public static long bytesToMegabytes(long bytes) {
return bytes / MEGABYTE;
}
public static void main(String[] args) {
// I assume you will know how to create an object Person yourself...
List <Person> list = new ArrayList <Person> ();
for (int i = 0; i <= 100_000; i++) {
list.add(new Person("Jim", "Knopf"));
}
// Get the Java runtime
Runtime runtime = Runtime.getRuntime();
// Run the garbage collector
runtime.gc();
// Calculate the used memory
long memory = runtime.totalMemory() - runtime.freeMemory();
System.out.println("Used memory is bytes: " + memory);
System.out.println("Used memory is megabytes: " + bytesToMegabytes(memory));
}
}
Вопрос будет очень широким.
Это зависит от переменной класса, или вы можете вызвать использование памяти в java.
Он также требует дополнительной памяти для заголовков и ссылок.
Память кучи, используемая объектом Java, включает
память для примитивных полей в соответствии с их размером (размеры примитивных типов см. ниже);
память для справочных полей (по 4 байта);
заголовок объекта, состоящий из нескольких байтов «служебной» информации;
Для объектов в java также требуется некоторая "служебная" информация, такая как запись класса объекта, идентификатора и флагов состояния, например, доступен ли объект в данный момент, заблокирован ли в данный момент синхронизация и т. д.
Размер заголовка объекта Java варьируется на 32- и 64-битных jvm.
Хотя это основные потребители памяти, jvm также иногда требует дополнительных полей, например, для выравнивания кода и т. д.
Размеры примитивных типов
логическое и байтовое - 1
char & short - 2
int & float - 4
длинный и двойной - 8
Читатели также могут найти этот документ очень поучительным: cs.virginia.edu/kim/publicity/pldi09tutorials/…
Похоже, что каждый объект имеет накладные расходы в 16 байт в 32-битных системах (и 24 байта в 64-битных системах).
http://algs4.cs.princeton.edu/14analysis/ - хороший источник информации. Среди многих хороших примеров можно привести следующий.

http://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efficient-java-tutorial.pdf тоже очень информативный, например:

«Похоже, что на каждый объект приходится 16 байтов в 32-битных системах (и 24 байта в 64-битных системах)». Это неправильно, по крайней мере, для текущих JDK. Взгляните на мой пример отвечать для целого числа. Накладные расходы объекта составляют не менее 12 байт для заголовка для 64-битной системы и современного JDK. Может быть больше из-за заполнения, зависит от фактического расположения полей в объекте.
Вторая ссылка на учебник по Java с эффективным использованием памяти кажется мертвой - я получаю «Запрещено».
Это зависит от архитектуры / jdk. Для современной архитектуры JDK и 64-битной архитектуры объект имеет 12-байтовый заголовок и заполнение на 8 байтов, поэтому минимальный размер объекта составляет 16 байтов. Вы можете использовать инструмент под названием Макет объекта Java, чтобы определить размер и получить подробную информацию о макете объекта и внутренней структуре любого объекта или угадать эту информацию по ссылке на класс. Пример вывода для Integer в моей среде:
Running 64-bit HotSpot VM.
Using compressed oop with 3-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]
java.lang.Integer object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 4 int Integer.value N/A
Instance size: 16 bytes (estimated, the sample instance is not available)
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
Итак, для Integer размер экземпляра составляет 16 байтов, потому что 4-байтовые int сжимаются на месте сразу после заголовка и перед границей заполнения.
Пример кода:
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.util.VMSupport;
public static void main(String[] args) {
System.out.println(VMSupport.vmDetails());
System.out.println(ClassLayout.parseClass(Integer.class).toPrintable());
}
Если вы используете maven, чтобы получить JOL:
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.3.2</version>
</dependency>
Is the memory space consumed by one object with 100 attributes the same as that of 100 objects, with one attribute each?
Нет.
How much memory is allocated for an object?
How much additional space is used when adding an attribute?
char - это 16 бит, а не 8 бит.
вы правы. кто-то, кажется, отредактировал мой исходный ответ
Фактически, один экземпляр SingleByte займет 16 байтов на Sun JVM, то есть 8 байтов служебных данных, 4 байта для поля и затем 4 байта для заполнения объекта, поскольку компилятор HotSpot округляет все до кратных 8.