Alamat memori variabel di Java

143

Silakan lihat gambar di bawah ini. Saat kita membuat objek di java dengan newkata kunci, kita mendapatkan alamat memori dari OS.

Ketika kita menulis out.println(objName)kita dapat melihat string "khusus" sebagai keluaran. Pertanyaan saya adalah:

  1. Apa keluaran ini?
  2. Jika itu adalah alamat memori yang diberikan oleh OS kepada kami:

    a) Bagaimana cara mengubah string ini menjadi biner?

    b) Bagaimana saya bisa mendapatkan satu alamat variabel integer?

teks alt

uzay95
sumber
5
Yah, saya tidak memilih karena pertanyaannya cukup jelas, hanya saran bahwa Anda harus membuatnya dalam teks sehingga orang dapat mencarinya
phunehehe
2
Menggunakan sun.misc.Unsafe adalah mungkin untuk mendapatkan alamat objek java. Untuk daftar program, lihat: javapapers.com/core-java/address-of-a-java-object
Joseph Kulandai
nilai yang ditunjukkan adalah representasi heksadesimal dari kode hash objek a1 & a2
Naveen

Jawaban:

172

Itu adalah nama kelas dan System.identityHashCode () yang dipisahkan oleh karakter '@'. Apa yang diwakili oleh kode hash identitas adalah spesifik-implementasi. Ini sering kali merupakan alamat memori awal dari objek, tetapi objek dapat dipindahkan ke memori oleh VM dari waktu ke waktu. Jadi (secara singkat) Anda tidak bisa mengandalkannya sebagai apa pun.

Mendapatkan alamat memori variabel tidak ada artinya di dalam Java, karena JVM bebas mengimplementasikan objek dan memindahkannya sesuai keinginan (objek Anda mungkin / akan berpindah-pindah selama pengumpulan sampah, dll.)

Integer.toBinaryString () akan memberi Anda integer dalam bentuk biner.

Brian Agnew
sumber
34
Hal menarik lainnya adalah kode hash identitas tidak dijamin unik. Misalnya pada JVM 64-bit ada 2 ^ 32 kode hash identitas tetapi 2 ^ 64 alamat memori .
Alex Jasmin
12
Sebenarnya, kode hash identitas tidak dapat diubah , jika tidak, kontrak hashCode () akan dilanggar.
Matt McHenry
1
Saya menggunakan ini untuk logging / debugging untuk menentukan di log ketika objek menunjuk ke objek yang sama, bukan yang setara. Untuk tujuan identityHashcodeini, tidak ada artinya, hanya saja tidak bisa dibilang sangat mudah. :)
Kereta luncur
@ BrianAgnew: Saya ingin tahu -> Mengapa dua objek memiliki kode hash yang sama. Saya bingung karena saya telah belajar di c atau c ++ setiap variabel atau objek memiliki lokasi memori yang berbeda. Kemudian di java Bagaimana dapat mengidentifikasi atau membedakan dua objek dengan hashCode yang sama.
Ved Prakash
1
@VedPrakash, kode hash objek memungkinkan objek disimpan dalam koleksi berciri. Jika Anda ingin membedakan dua objek yang berbeda, Anda cukup menggunakan persamaan referensi
Brian Agnew
36

Hal ini dimungkinkan dengan menggunakan sun.misc.Unsafe: lihat jawaban hebat ini dari @Peter Lawrey -> Apakah ada cara untuk mendapatkan alamat referensi?

Menggunakan kodenya untuk 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();
}

Saya menyiapkan tes ini:

    //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);

Inilah hasilnya:

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

Kesimpulan:

  • hashcode! = alamat
  • toString = class @ HEX (kode hash)
JBE
sumber
13

Itu adalah output dari implementasi "toString ()" Object. Jika kelas Anda mengganti toString (), itu akan mencetak sesuatu yang sama sekali berbeda.

Paul Tomblin
sumber
6

Ini bukan alamat memori Ini adalah classname @ hashcode

dimana

classname = nama lengkap yang memenuhi syarat atau nama absolut (yaitu nama paket diikuti dengan nama kelas)

hashcode = format heksadesimal (System.identityHashCode (obj) atau obj.hashCode () akan memberi Anda kode hash dalam format desimal)

Sunil Kumar Sahoo
sumber
5

Seperti yang dikatakan Sunil, ini bukan alamat memori, ini hanya kode hash

Untuk mendapatkan @ konten yang sama, Anda dapat:

Jika hashCode tidak diganti di kelas itu:

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

Jika hashCode diganti, Anda mendapatkan nilai asli dengan:

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

Ini sering dibingungkan dengan alamat memori karena jika Anda tidak menimpa hashCode (), alamat memori digunakan untuk menghitung hash.

Topera
sumber
1

Apa yang Anda dapatkan adalah hasil dari metode toString () dari kelas Object atau, lebih tepatnya, identityHashCode () seperti yang ditunjukkan oleh uzay95.

"Saat kami membuat objek di java dengan kata kunci baru, kami mendapatkan alamat memori dari OS."

Penting untuk disadari bahwa semua yang Anda lakukan di Java ditangani oleh Java Virtual Machine. JVMlah yang memberikan informasi ini. Apa yang sebenarnya terjadi dalam RAM sistem operasi host bergantung sepenuhnya pada implementasi JRE.

James P.
sumber
-1

Di Java, saat Anda membuat objek dari kelas sejenis Person p = new Person();, psebenarnya adalah alamat lokasi memori yang mengarah ke tipe Person.

Saat menggunakan statemenet untuk mencetak, pAnda akan melihat alamat. Kata newkunci membuat lokasi memori baru yang berisi semua variabel dan metode instan yang termasuk dalam class Persondan pmerupakan variabel referensi yang menunjuk ke lokasi memori tersebut.

Panduka Wedisinghe
sumber
di gambar Anda a1 dan a2 adalah dua alamat memori yang berbeda. itulah alasan di balik mendapatkan dua nilai yang berbeda.
Panduka Wedisinghe