web-dev-qa-db-ja.com

スタックガベージはJavaで収集されますか?

ヒープメモリは、Javaで収集されたガベージコレクションです。

スタックガベージも収集されますか?

スタックメモリはどのように再利用されますか?

57
giri

スタック上のメモリには、メソッドパラメータとローカル変数が含まれています(正確には、オブジェクトの参照とプリミティブ型の変数自体)。メソッドを終了すると、それは自動的に削除されます。変数が(オブジェクトへの)参照である場合、オブジェクト自体はヒープ上にあり、ガベージコレクターによって処理されます。

したがって、スタックはヒープと同じ方法でガベージコレクションされるわけではありませんが、スタックはそれ自体が自動メモリ管理の形式です(ガベージコレクションよりも前のバージョンです)。

A より詳細な回答はThomas Porninによって提供されます 、詳細についてはそれを調べてください。

36
Mnementh

スタックはJavaで収集されたガベージではありません。

特定のメソッド呼び出しに割り当てられたスタックは、メソッドが戻るときに解放されます。これは非常に単純なLIFO構造なので、ガベージコレクションは必要ありません。

スタックとガベージコレクションが相互作用する場所の1つは、スタック上の参照がGCルートであるということです(つまり、到達可能性が決定されるルート参照です)。

28
Joachim Sauer

スタックはガベージコレクションされる可能性があります。ただし、ほとんどのJVM実装では、「スタック」として処理されます。これは、定義上、ガベージコレクションを排除します。

スタックと呼ばれるのは、メソッドアクティベーションコンテキストの蓄積です。呼び出されたメソッドごとに、これはメソッド引数、ローカル変数、を含む概念構造です。呼び出し元メソッドのコンテキストへの非表示のポインター、および命令ポインターを保存するためのスロット。 Java言語自体からアクティベーションコンテキストにアクセスすることはできません。メソッドが終了すると(returnを使用するか、例外がスローされるため)、コンテキストは使用できなくなります)。メソッドAがメソッドBを呼び出すと、Aが制御を取り戻すと、Bのコンテキストが役に立たなくなることが保証されます。これは、Bのコンテキストの有効期間がAのコンテキストの有効期間のサブレンジであることを意味します。したがって、(特定のスレッドの)アクティベーションコンテキストは、LIFO( "後入れ先出し")の規律で割り当てることができます。簡単に言うと、スタック:新しいアクティベーションコンテキストがプッシュされます。コンテキストのスタックの最上位であり、最上位のコンテキストが最初に破棄されます。

実際には、アクティベーションコンテキスト(スタックフレームとも呼ばれます)は、スタック順に、専用領域に連結されます。その領域は、スレッドの開始時にオペレーティングシステムから取得され、スレッドの終了時にオペレーティングシステムが取得します。スタックの最上位は特定のポインターによって指定され、多くの場合CPUレジスターに含まれます(これは、JVMがコードを解釈しているかコンパイルしているかによって異なります)。 「呼び出し元のコンテキストへのポインタ」は仮想です。呼び出し元のコンテキストは、必然的にスタック順にすぐ下に配置されます。 GCは介入しません。スタックの領域は、スレッドアクティビティ自体から同期的に作成され、再利用されます。これは、GCがまったくない [〜#〜] c [〜#〜] などの多くの言語でも機能します。

これで、JVM実装が他のことを行うのを妨げるものは何もありません。ヒープ内のアクティベーションコンテキストを割り当て、GCによって収集されます。これは通常、スタック割り当てが高速であるため、Java仮想マシンでは実行されません。しかし、他のいくつかの言語、特に 継続 で再生する言語は、そのようなことを実行する必要があります。 GCを使用する(例: Scheme およびその call-with-current-continuation 関数)、そのようなゲームは上記で説明したLIFOルールに違反するため。

14
Thomas Pornin

メモリのスタック部分は、「スタック」のように機能します。私はそれが悪いように聞こえることを知っています、しかしそれはまさにそれがどのように機能するかです。データは、互いの上に、上に追加されます(pushed onto the stack)、上部から自動的に削除されます(popped off the stack)プログラムの実行中。ガベージコレクションではありません。データがスタックからポップされると、そのメモリは自動的に再利用されるため、ガベージコレクションする必要はありません。そして、再利用されたと言っても、割り当てが解除されるわけではありません。データがポップオフされるため、次のデータが格納されるスタックメモリ内の場所が減少するだけです。

もちろん、スタックについてまったく心配する必要がないというわけではありません。再帰関数を何度も実行すると、最終的にすべてのスタックスペースが使い果たされます。多くの関数を呼び出す場合、特にそれらに多くのパラメーターやローカル変数がある場合も同じです。

しかし、肝心なのは、関数がスコープに出入りするときに、スタックのメモリが自動的に使用され、再利用されるということです。したがって、プログラムの実行が終了すると、すべてのスタックメモリが解放され、オペレーティングシステムに解放されます。

8
Mike Dinescu

スタックで使用されているメモリを参照すると、ガベージコレクションは行われません。
Java仮想マシンは明示的なバイトコード命令を使用してスタック上のメモリを予約および解放します。これらの命令はコンパイラによって生成され、int、boolean、doubleなどのプリミティブの存続期間を管理します。スタック上のオブジェクト参照。
いわゆる末尾呼び出しの最適化を実装する計画があります。これは、使用されなくなったことがわかったらスタックから一部のエントリを削除しますが、これをすでにサポートしているjvmはわかりません。
したがって、スタック自体のガベージコレクションはなく、コンパイラだけがメモリ使用量を管理するためのプッシュおよびポップ命令を生成しました。

スタック自体はスレッドの一部です。スタックは、スレッドオブジェクトが作成され、スレッドが終了してスレッドオブジェクトが参照されなくなった後にガベージコレクションが行われるときに割り当てられます。

4
josefx

スタックにあるものはすべて、ガベージコレクターによってグローバルルートとして扱われます。ですから、確かに、スタックは「ガベージコレクション」であると言えます。

1
SK-logic

Java内のすべてのオブジェクトは、ヒープに割り当てられます(少なくとも仕様に関する限り、実際の実装では、オブジェクトがヒープ上にあるかのように透過的に動作する場合、スタックに割り当てることができます。 )

正確に収集できるものは少し微妙です。オブジェクトへの唯一の参照が単一のスタックフレーム内にあり、参照が再度使用されないことを示すことができる場合、オブジェクトが収集される可能性があります。オブジェクトがフィールドの読み取りにのみ使用される場合、そのフィールドの読み取りは前方に最適化され、オブジェクトは予想よりも早く収集される可能性があります。

ファイナライザー(またはおそらくReferences)を使用していない限り、これは通常問題ではありません。その場合は注意して、locks/volatileを使用してhappens-before関係を強制する必要があります。

スレッドが停止すると、通常、スタック全体の割り当てが解除されます。

いいえ。スタックはJavaで収集されたガベージではありません。各スレッドには独自のスタックがあり、次のものが含まれています。

  1. メソッド固有の値(短命)および
  2. ヒープ上に作成され、メソッドによって参照されているオブジェクトへの参照

これらの値は、メソッド呼び出しごとにスタックフレームとしてスタックにプッシュされます。スタックは「後入れ先出し」の順序に従うため、すべてのメソッド呼び出しの最後に、すべてのメソッド固有のデータとオブジェクトへの参照(存在する場合)を含む各スタックフレームがポップアウトされます。

したがって、メソッド/プログラムがスコープ外になると、スタック内のデータは自動的にクリーンアップされます。

0
Aks

メソッド内やメソッド呼び出し中などに内部変数があるため、データはスタックからプッシュおよびポップされません。これについて気にする必要はありません。

0
Axarydax