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 .