メソッドはどこにありますか?スタックまたはヒープ?
質問
ローカル変数とメソッドのパラメーターがスタックに存在することは知っていますが、Javaの場合、実際にメソッドがどこに存在するのかわかりませんか?
次のようなThreadオブジェクトを宣言した場合:
Thread t=new Thread();
t.start();
つまり、メインメソッドとは別にメソッドの呼び出しを個別に作成したことを意味します。どういう意味ですか?スタックメモリを介してメソッドの別のシーケンスを呼び出すことを意味しますか?私は正しいですか?
解決
各スレッドには独自のスタックが割り当てられます。
この記事には良い紹介がありますJavaプロセス内のメモリ分離に。
Java仮想マシン内で、それぞれ スレッドにはJavaスタックが授与されます。 他のスレッドができないデータを含む ローカル変数を含むアクセス、 パラメータ、およびそれぞれの戻り値 スレッドが呼び出したメソッド。の スタック上のデータは制限されています プリミティブ型とオブジェクト参照。 JVMでは、次のことはできません。 実際のオブジェクトの画像を配置します スタック。すべてのオブジェクトは ヒープ。
各スレッドがほとんど実行せず、メモリの問題に遭遇することに基づいて、クライアントが巨大なスレッドサーバーを実装する多くのシナリオを見てきました。これは、各スレッドに独自のスタックが割り当てられ、これが(明らかに)加算されるためです。デフォルト値はスレッドごとに512kであると考えますが、そのための正規のソースは見つかりませんでした。
他のヒント
正しく覚えていれば、メソッドコード自体はメモリのコード部分に存在し、内部で宣言された変数はスタックに存在し、オブジェクトはヒープ上に作成されます。 Javaでは、変数ポインタとプリミティブはスタックに存在し、作成されたオブジェクトはヒープに存在します。
(貧しい)ASCII表現の場合:
-------
|STACK|
-------
|FREE |
-------
|HEAP |
-------
|CODE |
-------
スタックがスタックを表し、FREEは空きメモリを表し、HEAPはヒープを表し、CODEはコードスペースを表します。
これは私の記憶が言うことです-詳細の一部は間違っているかもしれません。
スタックはメソッド呼び出しで構成されます。 javaがスタックにプッシュするのはメソッド呼び出しレコードで、そのメソッドのすべての変数(パラメーターとローカルにインスタンス化された変数の両方)をカプセル化します。 Javaアプリケーションを起動すると、メインメソッド(自動的にargsパラメーターが含まれます)がスタック上の唯一のものになります。
main(args)
Fooオブジェクトを作成してfoo.method()を呼び出すと、スタックは次のようになります。
method()
main(args)
メソッドが呼び出されると、メソッドはスタックにプッシュされ、メソッドが戻ると削除されるか、「ポップ」されます。スタックから。変数が宣言されて使用されると、現在のメソッド(スタックの最上部)に対応するスタックエントリが大きくなり、変数のサイズが含まれるようになります。
スレッドの例では、各スレッドは、他のスレッドのスタックとは無関係に存在する独自のスタックを持ちます。
スタックには、すべてのローカル変数とすべてのアクティブなメソッド呼び出しが含まれます。 ヒープは他のすべてを保持します。
あなたのサブ質問に関しては、それはそれ自身の専用メモリで新しいスタックが作成されることを意味しています。 新しいスレッドは、jvmによって割り当てられた合計ヒープスペース(メモリ)を共有します
ヒープは複数の世代に分割されます。
バイトコード、およびその対応するJITコンパイル済みマシンコードは、インターンされた文字列やその他のクラスデータとともに、いわゆる永続世代に存在します。
「永続的」と呼ばれているにもかかわらず世代、それはまだガベージコレクションできます。一部のライブラリ、フレームワーク、およびJVM言語は実行時にバイトコードを生成するため、永続的な生成ではクリーンアップが必要になる場合があります。ヒープの他の世代と同様ですが、(通常は希望する)頻度は低くなります。
実際のバイトコードやJITコードは、プロセスのメモリに存在します。特定のプロセス内のすべてのスレッドがそのメモリを共有しているため、プロセスメモリにはおそらく1つのコピーしかありません。これらのスレッドによって共有される変数はすべて、共通のメソッドによってアクセスされます。スレッドのローカル変数(スレッド内で使用されるメソッドローカル変数も含む)は、そのスレッドのメモリ内に作成されます。