hashCode
Мы знаем, что в Java все объекты наследуются отjava.lang.Object
Добрый. В этом классе есть наследуемый метод, называемыйhashCode()
. это вObject
Сигнатура метода в классе такова:
public native int hashCode();
Как видите, если объект не переопределяет этот метод, он унаследуетObject
Реализация класса представляет собойnative
Методы. На данный момент он будет основан наадрес памяти объектаВернуть хэш-значение.
Итак, мы запускаем следующий код, и он выводитfalse
:
public class HashCodeDemo {
public static void main(String[] args) {
Object objectA = new Object();
Object objectB = new Object();
System.out.println(objectA.hashCode() == objectB.hashCode());
}
}
Некоторые объекты требуютсодержимое полей объектадля вычисления хеш-значений, таких как строкиString
. В этой статье не описывается, как копироватьhashCode()
метод, вы можете изучить его самостоятельно, если вам интересно.
потому что он был скопированhashCode()
метод, поэтому следующий код выведетtrue
:
public class HashCodeDemo {
public static void main(String[] args) {
String s1 = "yasin shaw";
String s2 = "yasin shaw";
System.out.println(s1.hashCode() == s2.hashCode());
}
}
identityHashCode
что если объект перезаписываетhashCode
метод, мы все еще хотим получить значение хеша, вычисленное по его адресу памяти, что нам делать?
java.lang.System
Класс предоставляет статический метод:
public static native int identityHashCode(Object x);
Кстати, здесь мы коснемся знания о струнах:
public class HashCodeDemo {
public static void main(String[] args) {
String s1 = "yasin shaw";
String s2 = "yasin shaw";
System.out.println(s1.hashCode() == s2.hashCode());
System.out.println(System.identityHashCode(s1) == System.identityHashCode(s2));
String s3 = new String("yasin shaw");
String s4 = new String("yasin shaw");
System.out.println(s3.hashCode() == s4.hashCode());
System.out.println(System.identityHashCode(s3) == System.identityHashCode(s4));
}
}
// 输出:
true
true
true
false
Видно, что s1, s2 находятся впостоянный пулвнутри, поэтому их адреса памяти также будут равны, поэтому вызовитеidentityHashCode
метод вернетtrue
. Но s3, s4 есть вкучавнутри, так что звонитеidentityHashCode
метод вернетfalse
.
Связь с замком смещения?
Обычно мы называемСпособ вычисления HashCode в памяти"для"identity hash codeТак что на самом деле не покрытыObject
КатегорияhashCode()
Этот метод также известен как «идентификационный хэш-код».
Когда класс загружается,hashCode
хранится взаголовок объектавнутриMark Wordвнутри. В 32-битной JVM он будет занимать 25 бит, в 64-битной JVM — 31 бит.
Следует отметить, что упомянутый здесь hashCode относится только к идентификационному хэш-коду. Если это не идентификационный хэш-код, он не будет храниться в заголовке объекта.
Каждый объект Java имеет заголовок объекта. Если это не массив, используйте 2ширина словаЧтобы сохранить заголовок объекта, если это массив, он будет использовать 3 слова для хранения заголовка объекта. В 32-битной виртуальной машине слово имеет ширину 32 бита, в 64-битной виртуальной машине слово имеет ширину 64 бита. Содержимое заголовка объекта следующее:
длина | содержание | иллюстрировать |
---|---|---|
32/64bit | Mark Word | Сохраните хэш-код или информацию о блокировке объекта и т. д. |
32/64bit | Class Metadata Address | указатель на данные типа объекта |
32/64bit | Array length | длина массива (если это массив) |
Давайте посмотрим на структуру Mark Word (свободное от блокировки состояние):
32 бит:
25 bit | 4 bit | 1 bit | 2 bit |
---|---|---|---|
hashCode | возраст генерации объекта | Это нестандартный замок? | замок флаг |
64 бит:
25 bit | 31 bit | 1 bit | 4 bit | 1 bit | 2 bit |
---|---|---|---|---|---|
Неиспользованный | hashCode | cms_free | возраст генерации объекта | Это нестандартный замок? | замок флаг |
Обратите внимание, что это "безблокировочное состояние«Далее. Что делать, если есть состояние блокировки? Мы знаем, что после Java 6 существует три типа блокировок, уровни от низкого до высокого:Замок смещения, легкий замок, тяжелый замок.
Среди них как легкие блокировки, так и тяжелые блокировки будут создавать особое пространство в стеке потока.Displaced Mark Word, используется для копирования содержимого слова метки в заголовок объекта «замка» при получении блокировки и записи идентификатора текущего потока в слово метки; а когда блокировка снята, копирование заблокированного слова метки из смещенной метки Слово в.
А как насчет смещенного замка?
Когда объект вычислил идентификационный хэш-код, он не может войти в состояние предвзятой блокировки; когда объект в настоящее время находится в состоянии предвзятой блокировки и ему необходимо вычислить свой идентификационный хэш-код, его предвзятая блокировка будет отменена, а блокировка будет снята.Надуйте в тяжелый замок;
Когда объект вычисляет идентификационный хэш-код? Конечно, когда вы вызываете непокрытый метод Object.hashCode() или System.identityHashCode(Object o).