identityHashCode и предвзятая блокировка

Java

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).