Javaアプリケーションは、すべてのスレッドに対して1つのヒープで起動します。各スレッドには独自のスタックがあります。
Javaアプリケーションが開始されると、JVMオプション-Xms
および-Xmx
ヒープのサイズを制御し、-Xss
スタックサイズを制御します。
私の理解では、作成されるヒープはJVMの「管理された」メモリになり、作成されるすべてのオブジェクトはそこに配置されます。
しかし、スタック作成はどのように機能しますか? Java作成時に各スレッドのスタックを作成しますか?.
JVMはネイティブメモリからスタックを作成しますか、それとも管理されたメモリ領域のセクションをスタック用に事前に割り当てますか?もしそうなら、JVMはスレッドがどのように作成されるかをどのように知っていますか?
Java仕様 が示すスレッドスタックについて、いくつかのことがあります。とりわけ:
各Java仮想マシンスレッドには、スレッドと同時に作成されるプライベートJava仮想マシンスタックがあります。
Java仮想マシンスタックはプッシュフレームとポップフレームを除いて直接操作されることはないため、フレームはヒープに割り当てられます。Java仮想マシンスタックは連続している必要はありません。
仕様では、Java仮想マシンスタックを固定サイズにするか、計算の必要に応じて動的に拡張および縮小することができます。
これで、HotSpotなどのJVM実装に焦点を合わせると、さらに情報を取得できます。さまざまなソースから収集したいくつかの事実を以下に示します。
-Xss
オプション用です。 (ソース)Java SE 6の場合、Sparcのデフォルトは32ビットVMで512k、64ビットVMで1024kです。..- Xssオプション... 64kは、スレッドごとに許可されるスタックスペースの最小量です。
JVMは、ヒープよりも多くのメモリを使用することに注意してください。たとえば、Javaメソッド、スレッドスタック、ネイティブハンドルは、JVM内部データ構造と同様に、ヒープとは別のメモリに割り当てられます。
JavaスレッドとHotSpotのネイティブOSスレッドの間に直接マッピングがあります。 (ソース) 。
ただし、HotSpotのJavaスレッドスタックはソフトウェア管理であり、OSネイティブスレッドスタックではありません。 (ソース)
独立したソフトウェアスタックを使用してJava引数を渡しますが、ネイティブCスタックはVM自体によって使用されます。 JavaスレッドのプログラムカウンターまたはスタックポインターはC変数に格納されますが、これらは常にハードウェアレジスタに保持されるとは限りません。これらのソフトウェアインタープリター構造の管理はかなりの割合を消費します合計実行時間の。
JVMは、同じJavaネイティブメソッドとJVMランタイム呼び出し(クラスロードなど)のスレッドスタックも使用します。) (ソース) 。
興味深いことに、パフォーマンスの最適化として、割り当てられたオブジェクトでさえ、ヒープではなくスタックに配置される場合があります。 (ソース)
JVMは、エスケープ分析と呼ばれる手法を使用できます。これにより、特定のオブジェクトが存続期間全体にわたって単一のスレッドに限定されたままであり、その存続期間が特定のスタックフレームの存続期間によって制限されていることがわかります。このようなオブジェクトは、ヒープではなくスタックに安全に割り当てることができます。
そして、画像は千の言葉に値するので、ここにあるのは James Bloom
今、あなたの質問のいくつかに答えます:
JVMは、スレッドがどのように作成されるかをどのように知るのですか?
そうではありません。可変数のスレッドを作成することにより、矛盾によって簡単に証明できます。 スレッドの最大数と各スレッドのスタックサイズについていくつかの仮定を行います。そのため、割り当てるスレッドが多すぎると、メモリが不足する可能性があります(ヒープメモリではありません!)。
Java作成時にスレッドごとにスタックを作成しますか?
前述したように、each Java仮想マシンスレッドにはプライベートJavaと同時に作成される仮想マシンスタックがありますスレッド(ソース) .
もしそうなら、正確にスタックはメモリ上のどこにありますか?それは確かに「管理された」ヒープにはありません。
前述のとおり、 Java仕様 を使用すると、技術的に言えば、スタックメモリをヒープに格納できます。ただし、少なくともJRockit JVMはメモリの別の部分を使用します。
JVMはネイティブメモリからスタックを作成しますか、それとも管理されたメモリ領域のセクションをスタック用に事前に割り当てますか?
Java仕様 規定 動作方法:A Java =仮想マシンスタックはフレームを保存します(§2.6)。Java仮想マシンスタックは従来の言語のスタックに類似しています。1つの例外はネイティブメソッドスタックです。 native
メソッドに使用されます。これについては、 仕様 でもう一度説明します。
JVMは、ヒープよりも多くのメモリを使用します。たとえば、Javaメソッド、スレッドスタック、ネイティブハンドルは、JVM内部データ構造と同様に、ヒープとは別のメモリに割り当てられます。
さらに読む 。
質問に答えるには:
Java作成時にスレッドごとにスタックを作成しますか?
はい。
もしそうなら、正確にスタックはメモリ上のどこにありますか?
JVMではメモリを割り当てましたが、ヒープではありませんでした。
その場合、JVMはスレッドがどのように作成されるかをどのように知るのですか?
そうではありません。
JVMメモリを使い切って、取得するまで、好きなだけ作成できます。
Exception in thread "main" Java.lang.OutOfMemoryError: unable to create new native thread
編集:
上記のすべては Jrockit JVMを参照していますが、このような基本的な問題については他のJVMが異なるとは信じられません。