オブジェクトを作成すると、インスタンスフィールドとメソッドの両方、またはインスタンスフィールドのみに新しいメモリが割り当てられます


14

次のクラスがあります

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回です。

次の図を参照してください。どの図が正しい情報を提供しているかを教えてください。

ここに画像の説明を入力してください


1
あなたの研究を共有することは皆を助けます。あなたが何を試みたのか、なぜあなたのニーズに合わなかったのか教えてください。これは、あなたが時間をかけて自分自身を助けようとしていること、明白な答えを繰り返すことから私たちを救うこと、そして何よりもあなたがより具体的で関連性のある答えを得るのを助けることを示しています。また、を参照してください掲載する方法
ブヨ

3
私はJavaを学んでいます...そして、すべての資料では、オブジェクトを作成するたびにすべてのインスタンスフィールドに新しいメモリが割り当てられると言っています。しかし、新しいメモリがメソッドに割り当てられるか、またはない
Harish_N 14

回答:


13

メソッドのコードはClass(さらに簡潔にClass<Student>)の一部であり、クラスが最初にロードされるときにメモリにロードされます。

ただし、メソッドを実行すると、追加のメモリが使用され、パラメータ、ローカル変数、一時式の結果、戻り値などにメモリが割り当てられます。ただし、そのようなメモリはスタックに割り当てられます(新しいインスタンスの作成時に使用されるメモリはヒープに割り当てられます)

あなたの質問によると、図Bが正しいことは明らかです(実際にメソッドを呼び出したときに何が起こるかは反映されていません)。


OK。私は今90%クリアです...しかし、ちょっと疑い.. Student型のオブジェクトを10個作成した場合、Studentクラスに存在するメソッドに1セットの新しいメモリのみが割り当てられ、10セットの新しいメモリは10個のオブジェクトのインスタンス変数を保存するために割り当てられています。
Harish_N 14

正しい。メモリを取るのはプロパティだけではなく、インスタンス自体に関連する小さなオーバーヘッドがあると考えてください(プロパティのないクラスのインスタンスは0バイト以上のメモリを使用します)。
SJuan76 14

もう一つは...私は心の中でJavaを保つ質問を....同じことが..... Javaで起こるん
Harish_N

Java言語仕様では、いつどのような目的でメモリが割り当てられるかについては何も言及していません。それは実装者に任されており、実装者ごとに異なる方法を選択できます。
ヨルグWミットタグ14

6

インスタンスフィールド(プロパティバッキングフィールドを含む)は、NオブジェクトのNコピーを取得します。

静的フィールドは、クラスごとに1つのコピーを取得します。

メソッドは、プログラム「イメージ」または実行可能コードセグメントの一部であるバイトコードのブロック(またはJITの後、ネイティブ命令のブロック)です。メソッドは、ディスク上にあるプログラムイメージの一部です。OS(またはCLR)によってイメージがロードされると、メソッドコードの共有コピーが1つあります。

ホスト可能なコンパイラを使用して新しいメソッドをオンザフライでコンパイルできる場合を除き、これらは一般に「ヒープ」またはランタイム割り当ての一部ではありません。メソッドはオブジェクトのように「割り当て」られず、オブジェクトの作成に関連して「割り当て」られません。これらは、単一のオブジェクトがインスタンス化される前のプログラムの一部としてのみ存在します。ラムダ/デリゲートでさえ、その場で割り当てられません。コンパイラは、これらの動的に見える他のコードオブジェクトを実装するためにクラスをオンデマンドで作成し、ディスク上のバイトコードイメージの一部としても存在します。

コメントごとの更新:

JVM標準には、次のように記述されています。

2.5.4。メソッドエリア

Java仮想マシンには、すべてのJava仮想マシンスレッド間で共有されるメソッド領域があります。メソッド領域は、従来の言語のコンパイルされたコードの記憶領域に類似しているか、オペレーティングシステムプロセスの「テキスト」セグメントに類似しています。ランタイム定数プール、フィールドおよびメソッドデータなどのクラスごとの構造、およびクラスとインスタンスの初期化とインターフェイスの初期化で使用される特別なメソッド(§2.9)を含むメソッドとコンストラクターのコードを格納します。

メソッド領域は、仮想マシンの起動時に作成されます。メソッド領域は論理的にはヒープの一部ですが、単純な実装ではガベージコレクションもコンパクト化も選択しない場合があります。このバージョンのJava Virtual Machine仕様では、メソッド領域の場所や、コンパイルされたコードの管理に使用されるポリシーは必須ではありません。メソッド領域は固定サイズでも、計算の必要に応じて拡大してもよく、より大きなメソッド領域が不要になった場合は縮小できます。メソッド領域のメモリは連続している必要はありません。

したがって、(1)はい、仕様ではこれをどのように行うかは規定されていませんが、(2)従来の言語のコンパイル済みコードのストレージ領域に類似しています。テキストセグメント。これが私が述べているポイントです。


あなたが言っていることは理にかなっていますが、それは実際にJLSによって保証されていますか?通常、JLSは実装者にこのような質問に多くの余裕を与えます。
ヨルグWミットタグ14

その点については、@JörgWMittagではわかりません。君の言う通りかもね。私が作成しようとしたポイントは、「new T()」がメソッドの新しいインスタンスを割り当てないことです。JVMの詳細については、クラスローダーは実際にヒープにバイトコードを格納します。クラス自体がインスタンス化され、ガベージコレクションさえされる可能性のあるシナリオがあると思います。しかし、それはランタイムの実装の詳細であり、概念的には、私が話しているヒープは「ユーザー」ヒープです。クラスとメソッドは、通常のユーザーコンテキストのデータとは見なされません。しかし、ユーザーランドからクラスローダーを制御することもできるので、私は知りません。
コデンハイム14

JLSはヒープのことすらまったく話していませんよね?固定サイズの有限スタックと動的ヒープの代わりに、動的スタックとヒープなしでJavaを実装することは完全に合法です。また、JLSはJVMについて何も述べていません。JVMなしでJavaを実装することは完全に有効です。
ヨルグWミットタグ14

あなたはJLSを参照していますが、私はJVMについて話しています。JVM標準は確かにヒープについて議論しています。スタックのローカルスコープをエスケープする変数スコープ/ライフタイムを提供する必要があります。理論的に可能なことに関しては、「既知の実装」の観点から考えることを好みます。JVMは純粋なスタックマシンではないので、ヒーププリミティブなしで完全なJVMを実装するのは難しい作業であるか、不可能でさえあると確信しています。Forthマシンおよびその他の純粋なスタックアーキテクチャに関する私の理解では、ランダム変数アクセス用のプリミティブが存在する場合は可能かもしれませんが、私はそれを見たことがありません。
コデンハイム14

@JörgWMittag-議論に興味があるかもしれない何かを答えに追加しました。要点は、従来のランタイムシステムでの従来のコードまたはテキストセグメントとの類似性を引き出していたことです。
コデンハイム14

-4

ヒープメモリに割り当てられたオブジェクト。オブジェクトが割り当てられると、オブジェクトが破棄されるときにすべてのインスタンス変数のスロットが作成および破棄されます。そのため、インスタンス変数もヒープメモリに割り当てられます。そして、ローカル変数は、メソッドが呼び出されます。


1
これは、以前の回答で提供された情報を繰り返しているようです。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.