簡體   English   中英

Java中是否有用於原始類型的哈希碼/堆地址?

[英]is there hash code / Heap address for primitive types in Java?

我試圖在堆上找到一個近似的地址,你們給了我函數System.IdentityHashCode(Object)

問題是-此函數不適用於基本類型。 我會解釋原因。

作為輸入Java編譯程序-類文件。 我的目標是繪制一些圖形,其中包含一些時間之間的變量訪問信息。 我不知道代碼的樣子,我的策略是為每個LOAD和STORE指令設置自己的字節碼。 我正在使用ASM Java字節碼檢測。

因此,我無法執行以下操作:

identityHashCode(Integer.valueOf(...))

因為我沒有指示類型是否為int,double,long等。

我希望能夠確定同一類的不同實例之間:

例如 :

class foo {
int a;
}
foo b;
foo c;
b.a++;
c.a++;

但是當涉及字節碼時,名稱“ b” /“ c”與屬性a之間沒有關系。 我所看到的只是a遞增。 兩者都被視為! 如果那是Object a我可以使用System.identityHashCode()來區分它們。 但是我不能。

為了使自己清楚,請看以下示例:

package manipulate;

public class Test {
        int c;
        public static void main(String[] args) {
            Test a=new Test();
            Test b=new Test();
            a.c++;
            b.c++;
        }
    }

它將被翻譯(主要功能)為以下字節碼:

   L0
    LINENUMBER 7 L0
    NEW manipulate/Test
    DUP
    INVOKESPECIAL manipulate/Test.<init>()V
    ASTORE 1
   L1
    LINENUMBER 8 L1
    NEW manipulate/Test
    DUP
    INVOKESPECIAL manipulate/Test.<init>()V
    ASTORE 2
   L2
    LINENUMBER 9 L2
    ALOAD 1
    DUP
    GETFIELD manipulate/Test.c : I
    ICONST_1
    IADD
    PUTFIELD manipulate/Test.c : I
   L3
    LINENUMBER 10 L3
    ALOAD 2
    DUP
    GETFIELD manipulate/Test.c : I
    ICONST_1
    IADD
    PUTFIELD manipulate/Test.c : I
   L4
    LINENUMBER 11 L4
    RETURN

如您所見,我得到的只是整數c的值。 因此,鑒於該代碼,我無法確定這兩個c之間!

基元沒有身份。 它們是通過價值而不是參考進行比較的。 局部變量中的原語在內存中的地址可能位於寄存器中或堆棧中,並且數組或對象的原語成員的位置與其父級的堆地址有關。

Java沒有提供任何標准化的內存訪問工具,並且諸如System.identityHashCode類的替代項也沒有擴展到它們。

用原System.identityHashCodeSystem.identityHashCode將導致發生虛假裝箱,這將產生無意義的結果。

如果您確實需要了解原始成員的位置,則可以編寫具有JNI綁定的C代碼以獲取Java對象的句柄,獲取指針,並將其轉換為寬度合適的Java整數類型,但是最好最好是找到其他方法來做您想做的事情。

另一種選擇是使用現有的Java調試器掛鈎: http : //download.oracle.com/javase/6/docs/technotes/guides/jpda/architecture.html#jdi

我所擁有的是java bytecode。 我沒有b或c,我不知道它們。 我在堆棧上只有a的值

如果堆棧上有局部變量,則它們具有變量號。 這些數字對於在其中執行方法的堆棧框架來說是本地的,並且如果兩個變量具有相同的數字,則它們是相同的。

如果在評估(參數/操作數/結果)堆棧中有兩個原始值,則如果它們在同一堆棧索引中同時存在,則它們是相同的(含義與變量相同)。


在您的示例中,您看到兩個GETFIELD manipulate/Test.c : I指令均對堆棧上的當前值(由ALOAD 1ALOAD 2放置在ALOAD 2 )進行操作。 當前值是變量所屬的對象,因此您可以在其中插入該對象的計數代碼(首先執行DUP)。

我不確定我是否理解這個問題,您想知道ba實際上是否與ca相同?

在您的情況下,如果b == c,ba將與ca相同。 如果聲明一個靜態變量,它將在foo的所有實例之間共享。

當您詢問內存地址並得到identityhashCode答案時,關鍵短語是“某種近似值”。 不能保證此值將是內存地址,甚至最激進的斷言是它是從地址到整數的映射 您絕對不能可靠地確定Java中對象的地址,甚至不應該考慮嘗試使用基元。 一方面,不能保證編譯器不會移動它們。 甚至不能保證變量有地址。

如果要確定兩個對象是否相同,可以使用“ ==”。 這個問題甚至與基元都沒有意義,因此您不應該這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM