10
  1. オブジェクトが Java でインスタンス化されると、実際には何がメモリに格納されるのでしょうか?
  2. 親コンストラクターのコピーは含まれますか?
  3. キャスト時に非表示のデータ メンバーがオーバーライドされたメソッドと異なる動作をするのはなぜですか?

このようなものを正しく使用するために通常与えられる抽象的な説明は理解していますが、JVM は実際にどのようにそれを行うのでしょうか。

4

3 に答える 3

17

オブジェクトがインスタンス化されると、それを作成したオブジェクトのタイプへの参照とともに、非静的データのみが実際に「作成」されます。

どのメソッドもコピーされません。

それを作成したクラスへの「参照」は、実際にはポインタ ディスパッチ テーブルです。クラスで使用できるメソッドごとに 1 つのポインターが存在します。ポインターは常に、メソッドの「正しい」実装 (通常はオブジェクト ツリーで最も低い/最も具体的な実装) を指します。

そうすれば、別のメソッドへのトップレベルの呼び出しがあり、他のメソッドがオーバーライドされている場合、オーバーライドされたメソッドが呼び出されます。これは、テーブル内のポインターが指している場所であるためです。このメカニズムにより、最上位のメソッドよりもオーバーライドされたメソッドを呼び出すのに時間がかかることはありません。

ポインター テーブル + メンバー変数は、クラスの「インスタンス」です。

変数の問題は、まったく異なるメカニズムである「名前空間」に関係しています。変数はまったく「サブクラス化」されません (ディスパッチ テーブルには入りません) が、パブリック変数またはプロテクト変数はローカル変数によって非表示にすることができます。これはすべてコンパイル時にコンパイラによって行われ、ランタイム オブジェクト インスタンスとは関係ありません。コンパイラは、本当に必要なオブジェクトを判断し、その参照をコードに挿入します。

スコープ規則は、一般に「最も近い」変数を優先することです。同じ名前で遠くにあるものはすべて無視 (シャドウ) され、より近い定義が優先されます。

興味がある場合は、メモリ割り当てについてもう少し具体的に説明します。すべての「オブジェクト」は「ヒープ」に割り当てられます (実際には、真のヒープよりも驚くほど効率的で美しいものですが、同じ概念です)。変数は常にポインターです-Javaオブジェクトをコピーすることはありません。常にそのオブジェクトへのポインターをコピーします。メソッド パラメーターとローカル変数の変数ポインターの割り当てはスタック上で行われますが、変数 (ポインター) がスタック上に作成されても、それらが指すオブジェクトがスタック上に割り当てられることはありません。

例を書きたくなりましたが、これはすでに長すぎます。extends 関係を持ついくつかのクラスと、それらのメソッドとデータが生成されたコードにどのように影響するかを入力してほしい場合は、私に尋ねることができます.

于 2008-10-20T22:47:20.090 に答える
2

これが包括的な例であることがわかると思います。

http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html

于 2008-10-20T22:23:43.353 に答える