Перейти к основному содержимому

Адрес памяти объектов в Java

· 2 мин. чтения

1. Обзор

В этом кратком руководстве мы увидим, как найти адрес памяти объектов в Java.

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

В этом руководстве мы сосредоточимся на одной конкретной реализации JVM: HotSpot JVM. Мы также можем использовать термины JVM и HotSpot JVM как синонимы на протяжении всего руководства.

2. Зависимость

Чтобы найти адрес памяти объектов в JVM, мы собираемся использовать инструмент Java Object Layout ( JOL ). Поэтому нам нужно добавить зависимость jol-core :

<dependency> 
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.10</version>
</dependency>

3. Адрес памяти

Чтобы найти адрес памяти конкретного объекта в JVM, мы можем использовать метод addressOf() :

String answer = "42";

System.out.println("The memory address is " + VM.current().addressOf(answer));

Это напечатает:

The memory address is 31864981224

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

Кроме того, адреса памяти в большинстве реализаций JVM могут изменяться по мере того, как GC время от времени перемещает объекты.

4. Идентификационный хэш-код

Существует распространенное заблуждение, что адреса памяти объектов в JVM представлены как часть их реализаций toString по умолчанию , таких как java.lang.Object@60addb54 . То есть многие думают, что «60addb54» — это адрес памяти именно этого объекта.

Проверим это предположение:

Object obj = new Object();

System.out.println("Memory address: " + VM.current().addressOf(obj));
System.out.println("toString: " + obj);
System.out.println("hashCode: " + obj.hashCode());
System.out.println("hashCode: " + System.identityHashCode(obj));

Это напечатает следующее:

Memory address: 31879960584
toString: java.lang.Object@60addb54
hashCode: 1622006612
hashCode: 1622006612

Довольно интересно, что «60addb54» — это шестнадцатеричная версия хеш-кода, равная 1622006612. Метод hashCode() — один из общих методов для всех объектов Java. Если мы не объявляем метод hashCode() для класса, Java будет использовать для него идентификационный хэш-код.

Как показано выше, идентификационный хэш-код (часть после @ в toString ) и адрес памяти отличаются .

5. Вывод

В этом кратком руководстве мы увидели, как найти адрес памяти объектов в Java.

Как обычно, все примеры доступны на GitHub .