Будет ли .hashcode () возвращать другой int из-за сжатия пространства владения? - PullRequest
33 голосов
/ 26 сентября 2010

Если я вызываю метод Object.hashcode() для какого-либо объекта, он возвращает внутренний адрес объекта (реализация по умолчанию).Является ли этот адрес логическим или физическим адресом?

В сборке мусора из-за сжатия объектов памяти происходит смещение в памяти.Если я вызову хэш-код до и после GC, он вернет один и тот же хэш-код (он возвращает) и если да, то почему (из-за того, что адрес сжатия может измениться)?

Ответы [ 5 ]

45 голосов
/ 26 сентября 2010

@ Эриксон более или менее правильно.Хэш-код, возвращаемый java.lang.Object.hashCode(), не изменяется в течение времени жизни объекта.

Способ, которым это (обычно) реализуется, довольно умный.Когда объект перемещается сборщиком мусора, его оригинальный хеш-код должен храниться где-то на случай, если он будет использован снова.Очевидный способ реализовать это - добавить 32-битное поле в заголовок объекта для хранения хеш-кода.Но это добавило бы 1 слово к каждому объекту и потратило бы место в наиболее распространенном случае ... где метод Object hashCode не вызывается.

Решение состоит в том, чтобы добавить два бита флага кслово флага объекта и используйте их (примерно) следующим образом.Первый флаг устанавливается при вызове метода hashCode.Второй флаг сообщает методу hashCode, использовать ли текущий адрес объекта в качестве хеш-кода или использовать сохраненное значение.Когда GC запускается и перемещает объект, он проверяет эти флаги.Если первый флаг установлен, а второй не установлен, GC выделяет одно дополнительное слово в конце объекта и сохраняет исходное местоположение объекта в этом слове.Затем он устанавливает два флага.С тех пор метод hashCode получает значение хэш-кода из слова в конце объекта.


Фактически реализация identityHashCode 1014 * должна вести себя так чтобы выполнить следующую часть общего контракта хэш-кода :

"Всякий раз, когда он вызывается для одного и того же объекта более одного раза во время выполнения приложения Java,метод hashCode должен последовательно возвращать одно и то же целое число, при условии, что никакая информация, используемая в сравнениях сравнения для объекта, не изменяется . Это целое число не должно оставаться согласованным от одного выполнения приложения до другого выполнения того же приложения. "

Гипотетическая реализация identityHashCode(), которая просто возвращает текущий машинный адрес объекта, будет нарушать подсвеченную часть, если / когда GC переместит объект вдругой адрес.Единственный способ избежать этого - для (гипотетической) JVM гарантировать, что объект никогда не будет двигаться после того, как к нему был вызван hashCode.И это может привести к серьезным и неразрешимым проблемам с фрагментацией кучи.

5 голосов
/ 26 сентября 2010

Нет, хеш-код объекта по умолчанию не изменится.

В документации не говорится, что хеш-код является адресом, в нем говорится, что это на основе адреса. Учтите, что хэш-коды 32-битные, но есть 64-битные JVM. Очевидно, что непосредственное использование адреса не всегда будет работать.

Реализация зависит от JVM, но в JVM от Sun (Oracle) я считаю, что хэш-код кэшируется при первом обращении к нему.

0 голосов
/ 26 сентября 2010

По контракту hashCode он не может измениться по такой причине.

0 голосов
/ 26 сентября 2010

если хеш-код изменится, объект исчезнет в хэш-наборе, в который он был вставлен, и Sun будет залито жалобами.

0 голосов
/ 26 сентября 2010

В этой ссылке говорится, что действительно хеш-код по умолчанию является адресом JVM объекта, но если он перемещается - адрес остается согласованным.Я не знаю, насколько надежен этот источник, но я уверен, что разработчики этого метода продумали этот сценарий (что не является редким или угловым случаем) и обеспечили правильную функциональность этого метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...