0

私はヒープで対処するためのいくつかの近似を見つけようとしていました、そしてあなたたちは私に関数を与えましたSystem.IdentityHashCode(Object)

問題は、この関数がプリミティブ型に適合しないことです。その理由を説明します。

私は入力Javaコンパイル済みプログラム-クラスファイルとして与えられます。私の目標は、時間間の可変アクセスに関する情報を含むいくつかのグラフをプロットすることです。コードがどのように見えるかを前もって知りません。私の戦術は、すべてのLOADおよびSTORE命令に対して自分のバイトコードをインストルメント化することです。ASM JavaBytecodeInstrumentationを使用しています。

したがって、私は次のようなことはできません。

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の値だけです。したがって、そのコードを考えると、これら2つのcのどちらかを判断することはできません。

4

4 に答える 4

4

プリミティブには ID がありません。これらは、参照ではなく、値によって比較されます。ローカル変数のプリミティブのメモリ内のアドレスは、レジスタまたはスタックにある可能性が高く、配列またはオブジェクトのプリミティブ メンバーの位置は、その親のヒープ アドレスに関連しています。

Java は、標準化されたメモリ アクセス機能を提供しておらず、System.identityHashCodeそれらに拡張されていないような代替手段も提供していません。

プリミティブで呼び出すSystem.identityHashCodeと、無意味な結果をもたらす偽のボクシングが発生します。

プリミティブ メンバーの場所を本当に知る必要がある場合は、JNI バインディングを使用して C コードを記述し、Java オブジェクトへのハンドルを取得してポインターを取得し、それを適切な幅の Java 整数型に変換できますが、おそらく、あなたがやろうとしていることを行うための他の方法を見つけることです。

もう 1 つのオプションは、既存の Java デバッガー フックを使用することです: http://download.oracle.com/javase/6/docs/technotes/guides/jpda/architecture.html#jdi

于 2011-02-25T19:24:54.263 に答える
0

私は質問を理解しているかどうかわかりません.baが実際にcaと同じ変数であるかどうか知りたいですか?

あなたの場合、b==c の場合、ba は ca と同じになります。static を宣言すると、foo のすべてのインスタンス間で共有されます。

于 2011-02-25T19:29:25.970 に答える
0

メモリ アドレスについて質問し、identityhashCode の回答を得たとき、キー フレーズは「ある程度の概算」でした。この値がメモリ アドレスになるという保証はなく、最も積極的な主張でさえ、アドレスから整数へのマッピングであるということです。Java でオブジェクトのアドレスを確実に決定することは絶対にできず、プリミティブを試してみることさえ考えるべきではありません。1 つには、コンパイラがそれらを移動しないという保証はありません。変数にアドレスがあるという保証さえありません。

2 つのオブジェクトが同じかどうかを判断したい場合は、「==」を使用できます。質問はプリミティブでは意味がありません。それを行うべきではありません。

于 2011-02-25T19:36:38.460 に答える