Как JVM гарантирует, что System.identityHashCode() никогда не изменится?
-
21-08-2019 - |
Вопрос
Обычно реализация по умолчанию Object.hashCode()
является некоторой функцией выделенного адреса объекта в памяти (хотя это не предусмотрено JLS).Учитывая, что виртуальная машина шунтирует объекты в памяти, почему значение, возвращаемое System.identityHashCode()
никогда не изменяться в течение срока службы объекта?
Если это расчет "одним выстрелом" (размер объекта hashCode
вычисляется один раз и прячется в заголовке объекта или что-то в этом роде), то означает ли это, что два объекта могут иметь одинаковый identityHashCode
(если они будут впервые выделены по одному и тому же адресу в памяти)?
Решение
Современные JVM сохраняют значение в заголовке объекта.Я полагаю, что значение обычно вычисляется только при первом использовании, чтобы свести время, затрачиваемое на выделение объектов, к минимуму (иногда до дюжины циклов).Обычная JVM Sun может быть скомпилирована так, чтобы хэш-код идентификатора всегда был равен 1 для всех объектов.
Несколько объектов могут иметь один и тот же идентификационный хэш-код.Такова природа хэш-кодов.
Другие советы
Отвечая на второй вопрос, независимо от реализации, несколько объектов могут иметь один и тот же identityHashCode.
Видишь ошибка 6321873 для краткого обсуждения формулировки в javadoc и программы для демонстрации неуникальности.
Заголовок объекта в HotSpot состоит из указателя класса и слова "mark".
Исходный код структуры данных для слова mark можно найти по адресу markOop.hpp
файл.В этом файле есть комментарий, описывающий расположение слова mark в памяти:
hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
Здесь мы можем видеть, что хэш-код идентификатора для обычных объектов Java в 32-разрядной системе сохраняется в слове mark и имеет длину 25 бит.
Общим руководством по реализации функции хеширования является :
- один и тот же объект должен возвращать согласованный хэш-код, он не должен меняться со временем или зависеть от какой - либо переменной информации (например,алгоритм, заполняемый случайным числом или значениями изменяемых полей-членов
- хэш-функция должна иметь хорошее случайное распределение, и под этим я подразумеваю, что если вы рассматриваете хэш-код как сегменты, то 2 объекта должны быть сопоставлены с разными сегментами (хэш-кодами), насколько это возможно.Вероятность того, что 2 объекта будут иметь один и тот же хэш-код, должна быть редкой - хотя это может случиться.
Насколько я знаю, это реализовано для возврата ссылки, которая никогда не изменится в течение срока службы объектов .