Java посчитать размер объекта

Как получить размер объекта в Java

Краткое и практическое руководство по получению размера объекта в Java.

1. Обзор

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

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

2. Потребление памяти в Java

Хотя в Java нет оператора sizeof , на самом деле он нам не нужен. Все примитивные типы имеют стандартный размер, и обычно в них нет байтов заполнения или выравнивания. Тем не менее, это не всегда просто.

Хотя примитивы должны вести себя так, как если бы они имели официальные размеры, JVM может хранить данные любым удобным для себя способом, с любым количеством заполнений или накладных расходов . Он может хранить логическое[] в 64-разрядных длинных блоках , таких как Набор бит , выделять некоторые временные Объекты в стеке или оптимизировать некоторые переменные или вызовы методов, полностью исключив их из существования, заменяя их константами и т. Д… Но до тех пор, пока программа дает тот же результат, все в полном порядке.

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

Читайте также:  Отправка пост запроса java

2.1. Объекты, ссылки и классы-оболочки

Минимальный размер объекта составляет 16 байт для современного 64-разрядного JDK , так как объект имеет 12-байтовый заголовок, дополненный кратным 8 байтам. В 32-разрядном JDK накладные расходы составляют 8 байт, что кратно 4 байтам.

Ссылки имеют типичный размер 4 байта на 32-разрядных платформах и на 64-разрядных платформах с границей кучи менее 32 ГБ ( -Xmx32G ) и 8 байт для этой границы выше 32 ГБ.

Это означает, что 64-разрядной JVM обычно требуется на 30-50% больше места в куче.

Особенно важно отметить, что упакованные типы, массивы, Строки s и другие контейнеры, такие как многомерные массивы, требуют больших затрат памяти, поскольку они добавляют определенные накладные расходы . Например, когда мы сравниваем int примитив (который потребляет всего 4 байта) с объектом Integer , который занимает 16 байт, мы видим, что объем оперативной памяти составляет 300%.

3. Оценка Размера Объекта С Помощью Контрольно-Измерительных Приборов

Один из способов получить оценку размера объекта в Java-это использовать getObjectSize(объект) метод Инструментария интерфейса , представленный в Java 5.

Как мы могли видеть в документации Javadoc, метод обеспечивает “аппроксимацию для конкретной реализации” размера указанного объекта. Примечательно, что существует потенциальное включение накладных расходов в размер, и значения могут отличаться во время одного вызова JVM.

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

3.1. Создание Агента Инструментирования

Для того, чтобы позвонить Instrumentation.getObjectSize(объект) чтобы получить размер объекта, нам сначала нужно получить доступ к экземпляру Instrumentation. Нам нужно использовать агент инструментирования и есть два способа сделать это, как описано в документации для пакета java.lang.instrument .

Агент инструментирования может быть указан через командную строку, или мы можем использовать его с уже запущенной JVM . Мы сосредоточимся на первом.

Чтобы указать агент инструментирования через командную строку , нам понадобится реализация перегруженного предварительного метода, который будет сначала вызван JVM при использовании инструментирования. Кроме того, нам нужно предоставить статический метод для доступа к Инструментам.getObjectSize(объект) .

Давайте теперь создадим класс Агент инструментирования :

public class InstrumentationAgent < private static volatile Instrumentation globalInstrumentation; public static void premain(final String agentArgs, final Instrumentation inst) < globalInstrumentation = inst; >public static long getObjectSize(final Object object) < if (globalInstrumentation == null) < throw new IllegalStateException("Agent not initialized."); >return globalInstrumentation.getObjectSize(object); > >

Прежде чем мы создадим JAR для этого агента, нам нужно убедиться, что в него включен простой метафайл MANIFEST.MF :

Premain-class: com.baeldung.objectsize.InstrumentationAgent

Теперь мы можем создать банку агента с включенным файлом MANIFEST.MF. Один из способов-через командную строку:

javac InstrumentationAgent.java jar cmf MANIFEST.MF InstrumentationAgent.jar InstrumentationAgent.class

3.2. Пример Класса

Давайте посмотрим на это в действии, создав класс с образцами объектов, которые будут использовать наш класс агента:

public class InstrumentationExample < public static void printObjectSize(Object object) < System.out.println("Object type: " + object.getClass() + ", size: " + InstrumentationAgent.getObjectSize(object) + " bytes"); >public static void main(String[] arguments) < String emptyString = ""; String string = "Estimating Object Size Using Instrumentation"; String[] stringArray = < emptyString, string, "com.baeldung" >; String[] anotherStringArray = new String[100]; List stringList = new ArrayList<>(); StringBuilder stringBuilder = new StringBuilder(100); int maxIntPrimitive = Integer.MAX_VALUE; int minIntPrimitive = Integer.MIN_VALUE; Integer maxInteger = Integer.MAX_VALUE; Integer minInteger = Integer.MIN_VALUE; long zeroLong = 0L; double zeroDouble = 0.0; boolean falseBoolean = false; Object object = new Object(); class EmptyClass < >EmptyClass emptyClass = new EmptyClass(); class StringClass < public String s; >StringClass stringClass = new StringClass(); printObjectSize(emptyString); printObjectSize(string); printObjectSize(stringArray); printObjectSize(anotherStringArray); printObjectSize(stringList); printObjectSize(stringBuilder); printObjectSize(maxIntPrimitive); printObjectSize(minIntPrimitive); printObjectSize(maxInteger); printObjectSize(minInteger); printObjectSize(zeroLong); printObjectSize(zeroDouble); printObjectSize(falseBoolean); printObjectSize(Day.TUESDAY); printObjectSize(object); printObjectSize(emptyClass); printObjectSize(stringClass); > public enum Day < MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY >>

Чтобы это сработало, нам нужно включить опцию – javaagent с путем к JAR агента при запуске нашего приложения :

VM Options: -javaagent:"path_to_agent_directory\InstrumentationAgent.jar"

Результаты запуска нашего класса покажут нам предполагаемые размеры объектов:

Object type: class java.lang.String, size: 24 bytes Object type: class java.lang.String, size: 24 bytes Object type: class [Ljava.lang.String;, size: 32 bytes Object type: class [Ljava.lang.String;, size: 416 bytes Object type: class java.util.ArrayList, size: 24 bytes Object type: class java.lang.StringBuilder, size: 24 bytes Object type: class java.lang.Integer, size: 16 bytes Object type: class java.lang.Integer, size: 16 bytes Object type: class java.lang.Integer, size: 16 bytes Object type: class java.lang.Integer, size: 16 bytes Object type: class java.lang.Long, size: 24 bytes Object type: class java.lang.Double, size: 24 bytes Object type: class java.lang.Boolean, size: 16 bytes Object type: class com.baeldung.objectsize.InstrumentationExample$Day, size: 24 bytes Object type: class java.lang.Object, size: 16 bytes Object type: class com.baeldung.objectsize.InstrumentationExample$1EmptyClass, size: 16 bytes Object type: class com.baeldung.objectsize.InstrumentationExample$1StringClass, size: 16 bytes

4. Заключение

В этой статье мы описали, как память используется определенными типами в Java, как JVM хранит данные и подчеркивали вещи, которые могут повлиять на общее потребление памяти. Затем мы продемонстрировали, как мы можем на практике получить расчетный размер объектов Java.

Как всегда, полный код, связанный с этой статьей, можно найти в проекте GitHub .

Читайте ещё по теме:

Источник

Определение размера объекта в Java

Часто при работе с Java возникает задача определения размера объекта. Например, в приложении происходит чтение большого CSV файла и создание объектов на основе его строк. Чтобы избежать ошибки OutOfMemoryError , важно контролировать объем используемой памяти и корректно ограничивать количество создаваемых объектов.

Как узнать размер объекта?

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

Один из таких подходов — использование инструментария java.lang.instrument . Он предоставляет метод Instrumentation.getObjectSize(Object) , который возвращает приближенный размер объекта в байтах. Но стоит заметить, что для его использования необходимо внести изменения в параметры запуска JVM.

Определение размера примитивных типов и ссылок на объекты

Размер примитивных типов в Java стандартизирован и определен в официальной документации:

  • byte : 1 байт
  • short , char : 2 байта
  • int , float : 4 байта
  • long , double : 8 байтов
  • boolean : зависит от виртуальной машины

Размер ссылки на объект в Java также зависит от виртуальной машины и версии Java. На 32-битной JVM ссылка занимает 4 байта, на 64-битной — 8 байтов. Однако на 64-битной JVM с опцией CompressedOops (включена по умолчанию начиная с Java 6 update 23) размер ссылки составляет 4 байта.

Управление памятью в Java

Контролировать использование памяти в Java можно с помощью класса Runtime . Этот класс предоставляет методы для взаимодействия с Java Runtime Environment, включая управление памятью. Например, можно использовать Runtime.getRuntime().freeMemory() для определения объема свободной памяти или Runtime.getRuntime().totalMemory() для определения общего объема доступной памяти.

Вывод

Определение размера объекта в Java — не простая задача, требующая понимания работы JVM и управления памятью. Важно помнить о возможных ошибках и ограничениях при использовании различных подходов к ее решению.

Источник

Оцените статью