従来の Java プログラミングでは、Java オブジェクトやメモリ上の位置を扱う必要がなくなりました。 これについてフォーラムで議論すると、最初に浮かぶ疑問は、なぜ Java オブジェクトのアドレスを知る必要があるのかということです。 それはもっともな質問です。 しかし過去には、私たちは裁判を行う権利を留保していました。未知の領域で疑問を探求することは何も悪いことではありません。私は sun 社のパッケージを使用した実験を思いつきました。 Unsafe は sun.misc に属するパッケージです。もしかしたら、このパッケージには少し馴染みがないかもしれません。ソース コードとメソッドを見てみれば、私が何を指しているのかがわかるでしょう。
Java のセキュリティ管理は、メモリを簡単に変更できないようにするための十分な隠蔽機能を備えています。最初のステップとして、Java オブジェクトのメモリ位置を取得することを考えました。探索するまで、私は Java でオブジェクトのアドレスの場所を見つけることは不可能であると 100% 確信していました。
Sun の Unsafe.java API ドキュメントには、objectFieldOffset メソッドを使用してアドレスにアクセスできることが示されています。このメソッドは、「レポート内のクラスは、その場所をストレージの特定の領域に割り当てます。」と言っているように見えますが、「これは、Cookie が安全でないヒープ メモリに渡される単なるアクセサーです。」とも述べています。 とにかく、オブジェクトが格納されるメモリの場所をそのクラスのストレージから割り当てることができます。取得するのはオブジェクトの絶対物理メモリ アドレスではないと主張する人もいるでしょう。ただし、論理メモリアドレスは取得できました。次のプログラムはあなたにとって非常に興味深いものとなるでしょう!
最初のステップとして、Unsafe クラスのオブジェクトを取得する必要があります。コンストラクターはプライベートであるため、これは困難です。 安全でないオブジェクトを返す getUnsafe というメソッドがあります。 Java セキュリティ管理では、ソース コードに権限を与える必要があります。少し反省してインスタンスを作成しました。インスタンスを取得するより良い方法があることはわかっていますが、セキュリティ管理を回避するために次の方法を選択しました。
Unsafe オブジェクトを使用するには、objectFieldOffset と staticFieldOffset を呼び出すだけです。結果は、クラスのメモリ割り当てアドレスになります。
以下のサンプルプログラムはJDK1.6上で動作します。
パブリック クラス ObjectLocation {
プライベート静的 int apple = 10;
プライベート int オレンジ = 10;
public static void main(String[] args) throws Exception {
安全でない unsafe = getUnsafeInstance();
フィールド appleField = ObjectLocation.class.getDeclaredField("apple");
System.out.println("Apple の場所: "
+ unsafe.staticFieldOffset(appleField));
フィールド orangeField = ObjectLocation.class.getDeclaredField("orange");
System.out.println("オレンジの場所: "
+ unsafe.objectFieldOffset(orangeField));
}
private static Unsafe getUnsafeInstance() は SecurityException をスローします。
NoSuchFieldException、IllegalArgumentException、
IllegalAccessException {
フィールド theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true);
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
}