Java'daki değişkenlerin bellek adresi


139

Lütfen aşağıdaki resme bir göz atın. Java'da newanahtar kelimeyle bir nesne oluşturduğumuzda , işletim sisteminden bir bellek adresi alıyoruz.

Yazdığımızda out.println(objName)çıktı olarak "özel" bir dize görebiliriz. Sorularım:

  1. Bu çıktı nedir?
  2. OS tarafından bize verilen bellek adresiyse:

    a) Bu dizeyi ikiliye nasıl dönüştürebilirim?

    b) Bir tam sayı değişkeninin adresini nasıl alabilirim?

alternatif metin


5
Peki oy vermiyorum çünkü soru yeterince açık, metin içinde yapman gereken bir öneri, insanlar arayabilir
phunehehe

2
Sun.misc.Unsafe kullanarak bir java nesnesinin adresini almak mümkündür. Program listesi için bakınız: javapapers.com/core-java/address-of-a-java-object
Joseph Kulandai

sivri değer a1 & a2 nesnesinin hashcode'unun onaltılık temsilidir
Naveen

Yanıtlar:


167

Sınıf adı ve '@' karakteriyle ayrılmış System.identityHashCode () . Kimlik karma kodunun temsil ettiği, uygulamaya özgüdür. Genellikle nesnenin ilk bellek adresidir, ancak nesne zaman içinde VM tarafından belleğe taşınabilir. Yani (kısaca) hiçbir şeye güvenemezsiniz.

Değişkenlerin bellek adreslerini almak Java içinde anlamsızdır, çünkü JVM nesneleri uygulama ve uygun göründüğü gibi taşıma özgürlüğüne sahiptir (çöp toplama sırasında nesneleriniz hareket edebilir / hareket edecektir).

Integer.toBinaryString () size ikili biçimde bir tam sayı verir.


33
Bir başka ilginç nokta da kimlik karma kodlarının benzersiz olduğu garanti edilmemesidir. Örneğin 64 bit JVM'de 2 ^ 32 kimlik karma kodu ancak 2 ^ 64 bellek adresi vardır .
Alex Jasmin

11
Aslında, kimlik karma kodu değişemez , aksi takdirde hashCode () sözleşmesi ihlal edilir.
Matt McHenry

1
Nesneleri eşdeğer olanlar yerine aynı nesneye işaret ederken günlükleri belirlemek için günlük / hata ayıklama için bu kullanıyorum. Bu amaçlar için identityHashcodeanlamsız değildir, sadece kusursuz değildir. :)
Kızak

@BrianAgnew: Bilmek istiyorum -> Neden iki nesne aynı hashcode sahip. Her değişken veya nesnenin farklı bellek konumu var c veya c ++ öğrendim çünkü karıştı. Sonra java Nasıl aynı hashCode ile iki nesne tanımlamak veya ayırt edebilirsiniz.
Ved Prakash

1
@VedPrakash nesnesinin karma kodu, nesnelerin karma koleksiyonlarda saklanmasına izin verir. İki farklı nesneyi ayırt etmek istiyorsanız, sadece referans eşitliğini kullanabilirsiniz
Brian Agnew

36

Kullanmak mümkündür sun.misc.Unsafe: @Peter Lawrey'in bu harika cevabına bakın -> Referans adresi almanın bir yolu var mı?

PrintAddresses () için kodunu kullanma:

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

Bu testi kurdum:

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

İşte çıktı:

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

Sonuç:

  • hashcode! = adres
  • toString = class @ HEX (karma kod)

13

Bu, Object'in "toString ()" uygulamasının çıktısıdır. Sınıfınız toString () öğesini geçersiz kılarsa, tamamen farklı bir şey yazdırır.


6

Bu bellek adresi değil Bu, classname @ hashcode

nerede

classname = tam nitelikli ad veya mutlak ad (yani paket adı ve ardından sınıf adı)

hashcode = onaltılık biçim (System.identityHashCode (obj) veya obj.hashCode () size ondalık biçimde hashcode verecektir)


4

Sunil'in dediği gibi, bu bellek adresi değil, bu sadece karma kod

Aynı @ içeriği elde etmek için şunları yapabilirsiniz:

Bu sınıfta hashCode geçersiz kılınmadı:

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

HashCode geçersiz kılınırsa, orijinal değeri şu şekilde alırsınız:

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

Bu genellikle bellek adresiyle karıştırılır, çünkü hashCode () öğesini geçersiz kılmazsanız, bellek adresi karma değerini hesaplamak için kullanılır.


1

Ne elde ederseniz, Object sınıfının toString () yönteminin veya daha doğrusu uzay95 olarak identityHashCode () yönteminin sonucudur.

"Java'da yeni anahtar sözcükle bir nesne oluşturduğumuzda, işletim sisteminden bir bellek adresi alıyoruz."

Java'da yaptığınız her şeyin Java Sanal Makinesi tarafından ele alındığını fark etmek önemlidir. Bu bilgiyi veren JVM'dir. Ana bilgisayar işletim sisteminin RAM'inde gerçekte ne olacağı tamamen JRE'nin uygulanmasına bağlıdır.



0

Eğer böyle bir sınıftan bir nesne yapıyoruz zaman Java'da Person p = new Person();, paslında bir tür işaret edilen bir hafıza konumuna bir adresidir Person.

Yazdırmak için bir istatistik kullandığınızda pbir adres göreceksiniz. newAnahtar kelime içerdiği tüm örnek değişkenler ve yöntemleri içeren yeni bir bellek konumu yapar class Personve pbu bellek konumuna işaret eden bir referans değişkendir.


resminizde a1 ve a2 iki farklı bellek adresidir. iki farklı değer elde etmenin arkasındaki sebep budur.
Panduka Wedisinghe
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.