«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 по умолчанию, таких как [email protected]. То есть многие думают, что «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: [email protected]
hashCode: 1622006612
hashCode: 1622006612

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

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

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

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

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