2013-07-31 14 views
13

Sto cercando l'algoritmo di Object.hashCode().Algoritmo Object.hashCode()

Questo codice è nativo in Object.java.

È questo perché

(a) il codice è in assembly-- mai stato in Java o in qualsiasi altro HLL affatto

o

(b) semplicemente non siano comunicate

?

In entrambi i casi, sto cercando di entrare in possesso di un algoritmo (pseudo-codice o una spiegazione dettagliata) di "come hashCode() è calcolato" - quali sono i params andando nel suo calcolo e il calcolo si?

Si prega di notare: E 'la hashCode() of Object che sto cercando for-- non un altro come quello di String o hashmap/tavolo.

// ======================================= ==============================

il new Java docs - JDK 8 ora dicendo

"The value returned by hashCode() is the object's hash code, which is the object's memory address in hexadecimal." 
+3

Credo che sia nativo perché l'hashCode di Object è un identificatore di indirizzo di memoria, non in realtà un hash dei campi dell'oggetto . –

+0

Qualcuno deve aggiornare i documenti che stai citando. Perché è completamente sbagliato. –

risposta

0

E ' perché si basa su dettagli di basso livello che non sono esposti al codice Java. Alcune parti di base della libreria standard (come java.lang.Object) devono essere implementate nel codice nativo.

Come parte, è possibile trovare almeno uno interesting article che esegue ulteriori dettagli sull'implementazione di HotSpot.

1

hashCode è un metodo nativo, il che significa che una libreria di sistema viene chiamata internamente. Ciò è dovuto al fatto che internamente l'hashcode proverà a generare un numero in base alla posizione della memoria dell'oggetto. Questo codice è dipendente dalla macchina e probabilmente scritto in C.

Ma se siete veramente interessati per vedere il codice nativo, quindi seguire questo:

http://hg.openjdk.java.net/jdk7/jdk7-gate/jdk/file/e947a98ea3c1/src/share/native/java/

+0

Bene, questo è il problema: la posizione della memoria oggetto è l'unico parametro da inserire nel calcolo hashCode()? come va, magari sui bit inferiori dell'indirizzo? – Roam

8

Nonostante il Javadoc, l'algo solo può utilizzare il indirizzo come input. Ciò significa che anche se i nuovi oggetti usano lo stesso indirizzo nello spazio eden non avranno lo stesso hashCode.

C'è un numero di algos che potrebbe essere utilizzato e non tutti utilizzano l'indirizzo.

Nota: hashCode() è 31 bit.

BTW È possibile impostarlo con Unsafe.putInt(object, 1, value) su Hotspot.

Set<Integer> ints = new LinkedHashSet<>(); 
int negative = 0, nonneg = 0; 
for (int i = 0; i < 100; i++) { 
    System.gc(); 
    for (int j = 0; j < 100; j++) { 
     int h = new Object().hashCode(); 
     ints.add(h); 
     if (h < 0) negative++; 
     else nonneg++; 
    } 
} 
System.out.println("unique: " + ints.size() + " negative: " + negative + " non-neg: " + nonneg); 

stampe

unique: 10000 negative: 0 non-neg: 10000 

Utilizzando Unsafe

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 
theUnsafe.setAccessible(true); 
Unsafe unsafe = (Unsafe) theUnsafe.get(null); 

Object o = new Object(); 
System.out.println("From header " + Integer.toHexString(unsafe.getInt(o, 1L))); 
// sets the hashCode lazily 
System.out.println("o.hashCode() " + Integer.toHexString(o.hashCode())); 
// it's here now. 
System.out.println("after hashCode() From header " + Integer.toHexString(unsafe.getInt(o, 1L))); 
unsafe.putInt(o, 1L, 0x12345678); 
System.out.println("after change o.hashCode() " + Integer.toHexString(o.hashCode())); 

stampe

From header 0 
o.hashCode() 2260e277 
after hashCode() From header 2260e277 
after change o.hashCode() 12345678 
+1

"hashCode() che utilizza solo l'indirizzo dell'oggetto" sarebbe coerente con le specifiche in http://www.docjar.com/docs/api/java/lang/Object.html#hashCode. ma poi stai dicendo "anche se i nuovi oggetti usano lo stesso indirizzo, non avranno lo stesso hashCode". come è rotto questo legame? qualche altra locazione di memoria rispetto all'indirizzo di riferimento dell'oggetto (come quello di qualche membro, l'indirizzo finale/quantità di memoria che utilizza, alcune cose sul timestamp ...?) – Roam

+0

anche se incontra lo stesso hashCode per lo stesso oggetto ad ogni chiamata di hashCode() all'interno di una esecuzione ", solo l'indirizzo dell'oggetto per questo calcolo non sembra così giusto - troppo coerente con lo spazio della memoria, non così forte sulla casualità di hashcode. – Roam

+1

sarebbe un identificatore "handle" immutabile che rimarrebbe costante per la durata dell'oggetto. Molto probabilmente l'implementazione della VM dipende e probabilmente non avrà alcuna relazione con l'indirizzo di memoria, perché a causa delle operazioni GC tutti gli oggetti in Java sono rilocabili nella memoria fisica. – peterk

11

Native hashCode implementazione del metodo dipende dal JVM. Per impostazione predefinita in HotSpot restituisce un numero casuale, è possibile verificarlo nello source code (funzione get_next_hash)

+0

Thx per il collegamento interessante. – Roam