次のクラスがあります
class Student{
int rollNumber;
int marks;
public void setResult(int rollNumber, int marks){
this.rollNumber=rollNumber;
this.marks=marks;
}
public void displayResult(){
System.out.println("Roll Number= "+this.rollNumber+" Marks= "+this.marks);
}
}
次のように、タイプStudentの2つのオブジェクトを作成します
Student s1=new Student();
Student s2=new Student();
ここで、2つの異なるメモリセットがインスタンスフィールドに割り当てられます。今私の質問は、メモリがメソッド(setResult
およびdisplayResult
)に2回または1回割り当てられるかどうかです。
次の図を参照してください。正しい情報を提供している図を教えてください。
メソッドのコードはClass
の一部です(より簡潔には、Class<Student>
)そしてクラスが最初にロードされたときにメモリにロードされます。
つまり、メソッドを実行すると、追加のメモリが使用され、パラメータ、ローカル変数、一時式の結果、戻り値などにメモリが割り当てられます。ただし、このようなメモリはスタックに割り当てられます(新しいインスタンスの作成時に使用されるメモリはヒープに割り当てられます)。
あなたの質問に従って、図Bが正しいことは明らかです(ただし、実際にメソッドを呼び出したときに何が起こるかは反映されていません)。
インスタンスフィールド(プロパティバッキングフィールドを含む)は、NオブジェクトのNコピーを取得します。
静的フィールドは、クラスごとに1つのコピーを取得します。
メソッドは、プログラム「イメージ」または実行可能コードセグメントの一部であるバイトコードのブロック(またはJITの後のネイティブ命令のブロック)です。メソッドはディスク上にあるため、すでにプログラムイメージの一部です。 OS(またはCLR)によってイメージが読み込まれると、メソッドコードの共有コピーが1つあります。
ホスト可能なコンパイラーを使用して新しいメソッドをその場でコンパイルする場合を除いて、これらは一般に「ヒープ」またはランタイム割り当ての一部ではありません。メソッドはオブジェクトのように「割り当て」られず、オブジェクトの作成に関連して「割り当て」られません。これらは、単一のオブジェクトがインスタンス化される前に、単にプログラムの一部として存在します。ラムダ/デリゲートでさえ、その場で割り当てられません。コンパイラは、これらの他の動的に見えるコードオブジェクトを実装するためにオンデマンドでクラスを作成し、それらはディスク上のバイトコードイメージの一部としても存在します。
コメントごとの更新:
JVM標準はこれを言うべきです:
2.5.4。メソッド領域
Java仮想マシンには、すべてのJava仮想マシンスレッド間で共有されるメソッド領域があります。メソッド領域は、コンパイルされたコードのストレージ領域に類似しています従来の言語またはオペレーティングシステムプロセスの「テキスト」セグメントに類似しています。ランタイム定数プール、フィールドおよびメソッドデータなどのクラスごとの構造、およびメソッドとコンストラクターのコード(特殊なメソッドを含む)(§ 2.9)クラスとインスタンスの初期化およびインターフェースの初期化で使用されます。
メソッド領域は、仮想マシンの起動時に作成されます。メソッド領域は論理的にヒープの一部ですが、単純な実装では、ガベージコレクションまたは圧縮のどちらも行わないことを選択できます。このバージョンのJava仮想マシン仕様では、メソッド領域の場所やコンパイル済みコードの管理に使用されるポリシーは必須ではありません。メソッド領域は固定サイズであるか、必要に応じて拡張できますより大きなメソッド領域が不要になった場合は縮小される可能性があり、メソッド領域のメモリは連続している必要はありません。
したがって、(1)はい、仕様はこれがどのように行われるかを指示しないことは明らかですが、(2)これは、従来の言語のコンパイルされたコードのストレージ領域に類似しています。テキストセグメント。これがポイントです。