Cのfree()
関数と同様に、Javaでメモリを解放する方法はありますか?または、オブジェクトをnullに設定し、GCに依存する唯一のオプションですか?
Cのfree()
関数と同様に、Javaでメモリを解放する方法はありますか?または、オブジェクトをnullに設定し、GCに依存する唯一のオプションですか?
回答:
Javaはマネージメモリを使用するため、メモリを割り当てることができる唯一の方法はnew
演算子を使用することであり、メモリの割り当てを解除できる唯一の方法は、ガベージコレクターに依存することです。
このメモリ管理ホワイトペーパー(PDF)は、何が起こっているのかを説明するのに役立ちます。
を呼び出しSystem.gc()
て、ガベージコレクターをすぐに実行することを提案することもできます。ただし、コードではなく、Javaランタイムが最終的な決定を行います。
Javaのドキュメントによると、
gcメソッドを呼び出すと、Java仮想マシンが未使用のオブジェクトをリサイクルして、現在それらが使用しているメモリをすばやく再利用できるようにするための労力が費やされることを示しています。メソッド呼び出しから制御が戻ったとき、Java仮想マシンは、破棄されたすべてのオブジェクトからスペースを再利用するために最善の努力をしました。
System.gc()
完全に無視していると非常に信頼できる人から言われました。
オブジェクト参照をに明示的に設定することについて言及した人はいないようnull
です。
たとえばList<String>
、メソッドの最初にを宣言し、サイズが非常に大きくなったが、メソッドの途中までしか必要でなかったとします。この時点で、List参照をnull
に設定して、メソッドが完了する前にガベージコレクターがこのオブジェクトを再利用できるようにすることができます(いずれにしても、参照はスコープ外になります)。
このテクニックを実際に使用することはめったにありませんが、非常に大きなデータ構造を扱う場合は検討する価値があります。
System.gc();
ガベージコレクターを実行します。
gcメソッドを呼び出すと、Java仮想マシンが未使用のオブジェクトをリサイクルして、現在それらが使用しているメモリをすばやく再利用できるようにするための労力が費やされることを示しています。メソッド呼び出しから制御が戻ったとき、Java仮想マシンは、破棄されたすべてのオブジェクトからスペースを回収するために最善の努力をしました。
推奨されません。
編集:私は2009年に元の応答を書きました。それは現在2015年です。
ガベージコレクターは、Javaが登場してから約20年で着実に改善されてきました。この時点で、ガベージコレクターを手動で呼び出す場合は、他の方法を検討することをお勧めします。
*「私は個人的に、将来の適切な削除のためのプレースホルダーとしてnull変数に依存しています。たとえば、配列自体を実際に削除(nullにする)する前に、配列のすべての要素をnullにするのに時間をかけています。」
これは不要です。Java GCが機能する方法は、それらへの参照がないオブジェクトを見つけることです。そのため、参照(=変数)aを持つオブジェクトxがある場合、それを参照するため、GCはそれを削除しません。そのオブジェクトに:
a -> x
あなたがnをnullした場合、これが起こります:
a -> null
x
したがって、xはそれを指す参照を持たず、削除されます。同じことは、x以外のオブジェクトを参照するようにaを設定した場合にも発生します。
したがって、オブジェクトx、y、zを参照する配列arrと、配列を参照する変数aがある場合、次のようになります。
a -> arr -> x
-> y
-> z
あなたがnをnullした場合、これが起こります:
a -> null
arr -> x
-> y
-> z
したがって、GCはarrに参照が設定されていないことを見つけ、それを削除します。これにより、次の構造が得られます。
a -> null
x
y
z
これで、GCはx、y、zを検出し、それらも削除します。配列内の各参照をnullにしても、何も改善されることはありません。コード内のCPU時間と領域を使い果たすだけです(それは、それ以上害はありません。GCは、必要な方法を実行できます。 )。
任意のプログラム(Javaかどうかに関係なく)からメモリを解放したい正当な理由は、オペレーティングシステムレベルで他のプログラムが利用できるメモリを増やすことです。私のJavaアプリケーションが250MBを使用している場合は、強制的に1MBにして、249MBを他のアプリで使用できるようにすることができます。
Yiannis XanthopoulosとHot Licksによる回答とコメントを拡張するには(申し訳ありませんが、まだコメントできません!)、次の例のようにVMオプションを設定できます。
-XX:+UseG1GC -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=30
私のjdk 7では、VMがアイドル状態のときにGC後にヒープの30%以上が解放されると、未使用のVMメモリが解放されます。これらのパラメータを調整する必要があるでしょう。
以下のリンクでは強調されていませんが、一部のガベージコレクターはこれらのパラメーターに従わない場合があり、デフォルトでjavaがこれらのいずれかを選択する場合があることに注意してください(複数のコアがある場合(したがって上記のUseG1GC引数) )。
更新:java 1.8.0_73の場合、JVMが時折デフォルト設定で少量をリリースするのを見ました。ヒープの約70%が未使用の場合にのみそれを行うように見えますが、OSの物理メモリが不足している場合に、より積極的な解放になるかどうかはわかりません。
私はこれについて実験をしました。
System.gc();
ガベージコレクターの実行のみを提案しているのは事実です。
ただし、System.gc();
すべての参照をに設定してから呼び出すnull
と、パフォーマンスとメモリ使用率が向上します。
完全にjavacoffeebreak.com/faq/faq0012.htmlから
優先度の低いスレッドは、ユーザーのガベージコレクションを自動的に処理します。アイドル時間中にスレッドが呼び出されると、Javaのオブジェクトに以前割り当てられていたメモリを解放できます。しかし、心配しないでください-それはあなたのオブジェクトを削除しません!
オブジェクトへの参照がない場合、それはガベージコレクタにとって公正なゲームになります。いくつかのルーチン(C ++のfreeなど)を呼び出すのではなく、オブジェクトへのすべての参照をnullに割り当てるか、新しいクラスを参照に割り当てます。
例:
public static void main(String args[]) { // Instantiate a large memory using class MyLargeMemoryUsingClass myClass = new MyLargeMemoryUsingClass(8192); // Do some work for ( .............. ) { // Do some processing on myClass } // Clear reference to myClass myClass = null; // Continue processing, safe in the knowledge // that the garbage collector will reclaim myClass }
コードが大量のメモリを要求しようとしている場合は、低優先度スレッドとして許可するのではなく、ガベージコレクターにスペースの再利用の開始を要求することができます。これを行うには、次をコードに追加します
System.gc();
ガベージコレクターは空き領域を再利用しようとします。アプリケーションは、可能な限り多くのメモリを再利用して実行を継続できます(特定のプラットフォームでは、メモリの断片化の問題が発生する可能性があります)。
*「たとえば、サイズが非常に大きくなるメソッドの最初にリストを宣言したが、メソッドの途中までしか必要でなかったとします。この時点で、リスト参照をnullに設定できます。メソッドが完了する前にガベージコレクターがこのオブジェクトを再利用できるようにします(そして、参照はいずれにしてもスコープ外になります)。」*
これは正しいですが、このソリューションは一般化できない場合があります。Listオブジェクト参照をnullに設定すると、ガベージコレクションでメモリを使用できるようになりますが、これはプリミティブ型のListオブジェクトにのみ当てはまります。代わりにListオブジェクトに参照タイプが含まれている場合、Listオブジェクト= nullを設定しても、リストに含まれる参照タイプのいずれかが逆参照されません。この場合、Listオブジェクト= nullを設定すると、ガベージコレクションアルゴリズムが十分にスマートで、オブジェクトが孤立していると判断されない限り、オブジェクトがガベージコレクションで使用できない参照型が孤立します。
JAVAからの推奨はnullに割り当てることです
https://docs.oracle.com/cd/E19159-01/819-3681/abebi/index.htmlから
不要になった変数に明示的にnull値を割り当てると、ガベージコレクターが安全に再利用できるメモリの部分を特定するのに役立ちます。Javaはメモリ管理を提供しますが、メモリリークや過剰なメモリの使用を防ぐことはできません。
アプリケーションは、オブジェクト参照を解放しないことにより、メモリリークを引き起こす可能性があります。そうすることで、Javaガベージコレクターがそれらのオブジェクトを再利用できなくなり、メモリの使用量が増加します。使用後に変数への参照を明示的に無効にすると、ガベージコレクターがメモリを再利用できます。
メモリリークを検出する1つの方法は、プロファイリングツールを使用して、各トランザクションの後にメモリスナップショットを作成することです。定常状態のリークのないアプリケーションは、ガベージコレクション後に安定したアクティブヒープメモリを示します。