Will .hashcode () restituirà un int diverso a causa della compattazione dello spazio di possesso?

Se chiamo il metodo Object.hashcode() su qualche object restituisce l’indirizzo interno dell’object (implementazione predefinita). Questo indirizzo è un indirizzo logico o fisico?

Nella garbage collection, a causa degli oggetti di compattazione della memoria, lo spostamento avviene nella memoria. Se chiamo hashcode prima e dopo il GC, restituirà lo stesso hashcode (restituisce) e se sì, perché (a causa dell’indirizzo di compattazione potrebbe cambiare)?

@erickson è più o meno corretto. L’hashcode restituito da java.lang.Object.hashCode() non cambia per la durata dell’object.

Il modo in cui questo è (tipicamente) implementato è piuttosto intelligente. Quando un object viene spostato dal garbage collector, il suo codice hash originale deve essere memorizzato da qualche parte nel caso in cui venga utilizzato nuovamente. Il modo ovvio per implementare questo sarebbe aggiungere un campo a 32 bit all’intestazione dell’object per contenere l’hashcode. Ma ciò aggiungerebbe un overhead di 1 parola a ogni object, e sprecherebbe spazio nel caso più comune … dove non viene chiamato il metodo hashCode un object.

La soluzione consiste nell’aggiungere due bit di flag alla parola flag dell’object e usarli (approssimativamente) come segue. Il primo flag viene impostato quando viene chiamato il metodo hashCode . Un secondo flag indica al metodo hashCode se utilizzare l’indirizzo corrente dell’object come hashcode o se utilizzare un valore memorizzato. Quando GC esegue e riposiziona un object, verifica questi flag. Se il primo flag è impostato e il secondo è disinserito, il GC assegna una parola extra alla fine dell’object e memorizza la posizione dell’object originale in quella parola. Quindi imposta le due bandiere. Da quel momento in poi, il metodo hashCode ottiene il valore hashcode dalla parola alla fine dell’object.


In effetti, un’implementazione identityHashCode deve comportarsi in questo modo per soddisfare la seguente parte del contratto generale hashCode :

“Ogni volta che viene invocato sullo stesso object più di una volta durante un’esecuzione di un’applicazione Java, il metodo hashCode deve restituire costantemente lo stesso numero intero, a condizione che non vengano modificate le informazioni utilizzate nei confronti degli uguali sull’object . un’esecuzione di un’applicazione a un’altra esecuzione della stessa applicazione. “

Un’ipotetica implementazione di identityHashCode() che restituiva semplicemente l’indirizzo macchina corrente di un object violerebbe la parte evidenziata se / quando il GC spostasse l’object in un indirizzo diverso. L’unico modo per aggirare questo sarebbe la (ipotetica) JVM per garantire che un object non si muova mai una volta che hashCode è stato chiamato su di esso. E ciò porterebbe a problemi gravi e intrattabili con la frammentazione dell’heap.

No, il codice hash predefinito di un object non cambierà.

La documentazione non dice che il codice hash è l’indirizzo, dice che è basato sull’indirizzo. Considera che i codici hash sono a 32 bit, ma ci sono JVM a 64 bit. Chiaramente, l’uso diretto dell’indirizzo non funzionerebbe sempre.

L’implementazione dipende dalla JVM, ma nella JVM di Sun (Oracle), credo che il codice hash sia memorizzato nella cache la prima volta che si accede.

In questo link si dice che in effetti il ​​codice hash predefinito è l’indirizzo JVM dell’object, ma se viene spostato, l’indirizzo rimane coerente. Non so quanto sia affidabile questa fonte, ma sono sicuro che gli implementatori di questo metodo hanno pensato a questo scenario (che non è raro o caso d’angolo) e hanno assicurato la corretta funzionalità di questo metodo.

Con il contratto di hashCode non può cambiare per una tale ragione.

se l’hashcode cambia, l’object scomparirà in un set di hash in cui è stato inserito, e Sun sarà inondato di reclami.