Indirizzo di memoria delle variabili in Java


139

Si prega di dare un'occhiata alla foto qui sotto. Quando creiamo un oggetto in Java con la newparola chiave, otteniamo un indirizzo di memoria dal sistema operativo.

Quando scriviamo out.println(objName)possiamo vedere una stringa "speciale" come output. Le mie domande sono:

  1. Cos'è questo output?
  2. Se è l'indirizzo di memoria che ci è stato dato dal SO:

    a) Come posso convertire questa stringa in binario?

    b) Come posso ottenere un indirizzo per le variabili intere?

testo alternativo


5
beh, non sto votando verso il basso perché la domanda è abbastanza chiara, solo un suggerimento che avresti dovuto farlo nel testo in modo che la gente possa cercarlo
phunehehe

2
Usando sun.misc.Unsafe è possibile ottenere l'indirizzo di un oggetto Java. Per l'elenco dei programmi consultare: javapapers.com/core-java/address-of-a-java-object
Joseph Kulandai

il valore appuntito è la rappresentazione esadecimale dell'hashcode dell'oggetto a1 & a2
Naveen,

Risposte:


167

Questo è il nome della classe e System.identityHashCode () separati dal carattere '@'. Ciò che rappresenta il codice hash di identità è specifico dell'implementazione. Spesso è l'indirizzo di memoria iniziale dell'oggetto, ma l'oggetto può essere spostato in memoria dalla VM nel tempo. Quindi (brevemente) non puoi fare affidamento sul fatto che sia qualcosa.

Ottenere gli indirizzi di memoria delle variabili non ha senso in Java, poiché la JVM è libera di implementare oggetti e spostarli come sembra opportuno (i tuoi oggetti potrebbero / si muoveranno durante la garbage collection ecc.)

Integer.toBinaryString () ti darà un numero intero in forma binaria.


33
Un altro punto interessante è che i codici hash di identità non sono garantiti come unici. Ad esempio, su JVM a 64 bit sono presenti 2 ^ 32 codici hash identità ma 2 ^ 64 indirizzi di memoria .
Alex Jasmin,

11
In realtà, il codice hash dell'identità non può cambiare , altrimenti il ​​contratto di hashCode () verrebbe violato.
Matt McHenry,

1
Sto usando questo per la registrazione / debug per determinare nei registri quando gli oggetti puntano allo stesso oggetto invece di quelli equivalenti. Per questi scopi identityHashcodenon è privo di significato, semplicemente non è infallibile. :)
Slitta,

@BrianAgnew: Voglio sapere -> Perché due oggetti hanno lo stesso hashcode. Sono confuso perché ho imparato in c o c ++ che ogni variabile o oggetto ha una diversa posizione di memoria. Quindi in Java Come è possibile identificare o differenziare due oggetti con lo stesso hashCode.
Ved Prakash,

1
@VedPrakash l'oggetto hashcode consente di archiviare gli oggetti in raccolte con hash. Se vuoi differenziare due oggetti diversi, puoi semplicemente usare l'uguaglianza di riferimento
Brian Agnew,

36

È possibile usare sun.misc.Unsafe: vedi questa grande risposta da @Peter Lawrey -> C'è un modo per ottenere un indirizzo di riferimento?

Usando il suo codice per printAddresses ():

    public static void printAddresses(String label, Object... objects) {
    System.out.print(label + ": 0x");
    long last = 0;
    int offset = unsafe.arrayBaseOffset(objects.getClass());
    int scale = unsafe.arrayIndexScale(objects.getClass());
    switch (scale) {
    case 4:
        long factor = is64bit ? 8 : 1;
        final long i1 = (unsafe.getInt(objects, offset) & 0xFFFFFFFFL) * factor;
        System.out.print(Long.toHexString(i1));
        last = i1;
        for (int i = 1; i < objects.length; i++) {
            final long i2 = (unsafe.getInt(objects, offset + i * 4) & 0xFFFFFFFFL) * factor;
            if (i2 > last)
                System.out.print(", +" + Long.toHexString(i2 - last));
            else
                System.out.print(", -" + Long.toHexString( last - i2));
            last = i2;
        }
        break;
    case 8:
        throw new AssertionError("Not supported");
    }
    System.out.println();
}

Ho impostato questo test:

    //hashcode
    System.out.println("Hashcode :       "+myObject.hashCode());
    System.out.println("Hashcode :       "+System.identityHashCode(myObject));
    System.out.println("Hashcode (HEX) : "+Integer.toHexString(myObject.hashCode()));

    //toString
    System.out.println("toString :       "+String.valueOf(myObject));

    printAddresses("Address", myObject);

Ecco l'output:

Hashcode :       125665513
Hashcode :       125665513
Hashcode (HEX) : 77d80e9
toString :       java.lang.Object@77d80e9
Address: 0x7aae62270

Conclusione :

  • hashcode! = indirizzo
  • toString = class @ HEX (hashcode)

13

Questo è l'output dell'implementazione "toString ()" di Object. Se la tua classe ha la precedenza su String (), stamperà qualcosa di completamente diverso.


6

Questo non è un indirizzo di memoria Questo è classname @ hashcode

dove

classname = nome completo completo o nome assoluto (es. nome del pacchetto seguito dal nome della classe)

hashcode = formato esadecimale (System.identityHashCode (obj) o obj.hashCode () ti darà hashcode in formato decimale)


4

Come ha detto Sunil, questo non è un indirizzo di memoria , questo è solo l' hashcode

Per ottenere lo stesso @ contenuto, puoi:

Se hashCode non viene sovrascritto in quella classe:

"@" + Integer.toHexString(obj.hashCode())

Se hashCode viene sovrascritto, ottieni il valore originale con:

"@" + Integer.toHexString(System.identityHashCode(obj)) 

Questo è spesso confuso con l'indirizzo di memoria perché se non si ignora hashCode (), l'indirizzo di memoria viene utilizzato per calcolare l'hash.


1

Quello che stai ottenendo è il risultato del metodo toString () della classe Object o, più precisamente, dell'identitàHashCode () come ha sottolineato uzay95.

"Quando creiamo un oggetto in Java con una nuova parola chiave, otteniamo un indirizzo di memoria dal sistema operativo."

È importante rendersi conto che tutto ciò che fai in Java è gestito dalla Java Virtual Machine. È la JVM che fornisce queste informazioni. Ciò che effettivamente accade nella RAM del sistema operativo host dipende interamente dall'implementazione di JRE.



0

In Java quando si crea un oggetto da una classe come Person p = new Person();, in prealtà è un indirizzo di una posizione di memoria che punta a un tipo di Person.

Quando si utilizza un menu di stato per stampare p, verrà visualizzato un indirizzo. La newparola chiave crea una nuova posizione di memoria contenente tutte le variabili e i metodi di istanza inclusi in class Personed pè la variabile di riferimento che punta a quella posizione di memoria.


nella tua foto a1 e a2 ci sono due diversi indirizzi di memoria. Questa è la ragione per ottenere due valori diversi.
Panduka Wedisinghe,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.