Adres pamięci zmiennych w Javie

139

Proszę spojrzeć na poniższe zdjęcie. Kiedy tworzymy obiekt w java za pomocą newsłowa kluczowego, otrzymujemy adres pamięci z systemu operacyjnego.

Kiedy piszemy out.println(objName), na wyjściu widzimy „specjalny” ciąg. Moje pytania to:

  1. Co to za wynik?
  2. Jeśli jest to adres pamięci podany przez system operacyjny:

    a) Jak mogę zamienić ten ciąg na binarny?

    b) Jak mogę uzyskać jeden adres zmiennych całkowitych?

tekst alternatywny

uzay95
źródło
5
cóż, nie głosuję, ponieważ pytanie jest wystarczająco jasne, tylko sugestia, że ​​powinieneś był
napisać
2
Korzystając z sun.misc.Unsafe można uzyskać adres obiektu Java. Lista programów znajduje się pod adresem
Joseph Kulandai,
wskazana wartość jest szesnastkową reprezentacją hashcode obiektu a1 i a2
Naveen

Odpowiedzi:

166

To jest nazwa klasy i System.identityHashCode () oddzielone znakiem „@”. To, co reprezentuje kod skrótu tożsamości, jest specyficzne dla implementacji. Często jest to początkowy adres pamięci obiektu, ale obiekt może z czasem zostać przeniesiony do pamięci przez maszynę wirtualną. Więc (krótko) nie możesz polegać na tym, że to cokolwiek.

Pobieranie adresów pamięci zmiennych jest bez znaczenia w Javie, ponieważ JVM może implementować obiekty i przenosić je tak, jak wydaje się to odpowiednie (Twoje obiekty mogą / będą się poruszać podczas czyszczenia pamięci itp.)

Integer.toBinaryString () zwróci liczbę całkowitą w postaci binarnej.

Brian Agnew
źródło
33
Inną interesującą kwestią jest to, że nie ma gwarancji, że kody skrótów tożsamości będą unikalne. Na przykład w 64-bitowej JVM istnieje 2 ^ 32 kodów skrótu tożsamości , ale 2 ^ 64 adresy pamięci .
Alex Jasmin,
11
W rzeczywistości kod skrótu tożsamości nie może się zmienić , w przeciwnym razie doszłoby do naruszenia kontraktu funkcji hashCode ().
Matt McHenry
1
Używam tego do rejestrowania / debugowania w celu określenia w dziennikach, kiedy obiekty wskazują ten sam obiekt zamiast równoważnych. W tym celu identityHashcodenie jest bez znaczenia, po prostu nie jest niezawodny. :)
Sled
@BrianAgnew: Chcę wiedzieć -> Dlaczego dwa obiekty mają ten sam kod. Jestem zdezorientowany, ponieważ nauczyłem się w c lub c ++, każda zmienna lub obiekt ma inną lokalizację pamięci. Następnie w java Jak można zidentyfikować lub rozróżnić dwa obiekty z tym samym hashCode.
Ved Prakash,
1
@VedPrakash kod skrótu obiektu umożliwia przechowywanie obiektów w zaszyfrowanych kolekcjach. Jeśli chcesz rozróżnić dwa różne obiekty, możesz po prostu użyć równości odniesień
Brian Agnew,
36

Jest to możliwe, używając sun.misc.Unsafe: zobacz tę świetną odpowiedź od @Peter Lawrey -> Czy jest sposób na uzyskanie adresu referencyjnego?

Używanie jego kodu do 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();
}

Ustawiłem ten 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);

Oto wynik:

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

Wniosek:

  • hashcode! = adres
  • toString = class @ HEX (hashcode)
JBE
źródło
13

To jest wynik implementacji metody „toString ()” Object. Jeśli twoja klasa przesłania metodę toString (), wypisze coś zupełnie innego.

Paul Tomblin
źródło
6

To nie jest adres pamięci. To jest nazwa klasy @ hashcode

gdzie

nazwa klasy = pełna nazwa kwalifikowana lub nazwa bezwzględna (tj. nazwa pakietu, po której następuje nazwa klasy)

hashcode = format szesnastkowy (System.identityHashCode (obj) lub obj.hashCode () poda hashcode w formacie dziesiętnym)

Sunil Kumar Sahoo
źródło
4

Jak powiedział Sunil, to nie jest adres pamięci, to tylko hashcode

Aby uzyskać tę samą @ content, możesz:

Jeśli hashCode nie jest zastępowany w tej klasie:

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

Jeśli hashCode zostanie zastąpiony, otrzymasz oryginalną wartość z:

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

Jest to często mylone z adresem pamięci, ponieważ jeśli nie nadpisujesz hashCode (), adres pamięci jest używany do obliczania skrótu.

Topera
źródło
1

To, co otrzymujesz, jest wynikiem działania metody toString () klasy Object lub, dokładniej, identyfikacjiHashCode (), jak wskazał uzay95.

„Kiedy tworzymy obiekt w Javie z nowym słowem kluczowym, otrzymujemy adres pamięci z systemu operacyjnego”.

Ważne jest, aby zdać sobie sprawę, że wszystko, co robisz w Javie, jest obsługiwane przez wirtualną maszynę Java. To JVM przekazuje te informacje. To, co faktycznie dzieje się w pamięci RAM systemu operacyjnego hosta, zależy całkowicie od implementacji środowiska JRE.

James P.
źródło
0

W Javie, kiedy tworzysz obiekt z takiej klasy Person p = new Person();, w przeczywistości jest to adres lokalizacji pamięci, która wskazuje na typ Person.

Kiedy używasz statystyk do drukowania p, zobaczysz adres. newKluczowym słowem czyni nową lokalizację pamięci zawierającą wszystkie zmienne instancji i metod, które są zawarte w class Personi pjest zmienną odniesienia wskazując tym miejscu pamięci.

Panduka Wedisinghe
źródło
na twoim obrazku a1 i a2 to dwa różne adresy pamięci. to jest powód otrzymania dwóch różnych wartości.
Panduka Wedisinghe