たとえややこしくても、Javaでガベージコレクションを強制することは可能ですか?私はSystem.gc();
とRuntime.gc();
について知っていますが、彼らはGCをすることを提案するだけです。どうすればGCを強制できますか?
あなたの最善の選択肢は System.gc()
を呼び出すことです。これは単にコレクションを実行したいというガベージコレクタへのヒントです。ガベージコレクタは非決定的なので、強制的におよび即時収集する方法はありません。
jlibsライブラリにはガベージコレクションのための優れたユーティリティクラスがあります 。 WeakReference オブジェクトを使った気の利いた小さなトリックを使って、ガベージコレクションを強制することができます。
jlibから RuntimeUtil.gc() :
/**
* This method guarantees that garbage collection is
* done unlike <code>{@link System#gc()}</code>
*/
public static void gc() {
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
while(ref.get() != null) {
System.gc();
}
}
GCを強制する(唯一ではないにしても)最善の方法は、カスタムJVMを作成することです。ガベージコレクタはプラグ可能なので、おそらく利用可能な実装の1つを選んでそれを微調整することができます。
注:これは簡単な答えではありません。
Java™仮想マシンツールインタフェース(JVM TI) を使用して、関数
jvmtiError ForceGarbageCollection(jvmtiEnv* env)
「VMにガベージコレクションを強制的に実行させます。」 JVM TIは、 JavaTMプラットフォームデバッガアーキテクチャ(JPDA) の一部です。
YESメソッドを同じ順番で同時に呼び出さなければならないようにすることはほぼ可能です。
System.gc ();
System.runFinalization ();
この2つのメソッドの使用を同時にクリーンアップするためのオブジェクトが1つだけの場合でも、ガベージコレクタは、到達不可能なオブジェクトのfinalise()
メソッドを使用して、割り当てられたメモリを解放し、finalize()
メソッドの状態を実行します。
しかしながらこれを使うとソフトウェアよりも過負荷になる可能性があるのでガベージコレクタを使うのはひどい習慣です。ガベージコレクタは自分自身のスレッドを持ちます。これは制御することが不可能であり、gcによって使用されるアルゴリズムによっては時間がかかり、非常に非効率的であると考えられます。gcの助けを借りて最悪の場合はあなたのソフトウェアをチェックしてください。 GCに依存します。
注:これは、finalizeメソッドでオブジェクトの再割り当てが行われていない場合にのみ機能します。これが発生した場合、オブジェクトは存続し、技術的に可能な復活が発生します。
OutOfMemoryError のドキュメントでは、VMがフルガベージコレクションの後でメモリの回収に失敗しない限り、スローされないことを宣言しています。したがって、エラーが発生するまでメモリを割り当て続けると、すでにフルガベージコレクションが強制されたことになります。
おそらく、あなたが本当に尋ねたかったのは、「どうすればガベージコレクションで埋め立てるべきだと思うメモリを取り戻すことができるのか」ということでした。
手動でGCを要求するには(System.gc()からではありません):
.gcは将来のリリースでは廃止の候補です。Sunエンジニアはかつてコメントしたところで、世界の20人未満の人々が.gc()の使い方を実際に知っていると述べましたSecureRandomを使用したデータ構造は、40,000オブジェクトを過ぎたところで、vmがポインタを使い果たしたかのように遅くなるデータを生成しました。明らかにそれは16ビットのポインタテーブルをぎゅっとつぶしていて、古典的な「失敗する機械」の振る舞いを示しました。
私は-Xmsなどを試してみましたが、57、xxxになるまで少し動かし続けました。それから、キャンプEasy Moneyでコードが膨大になるのと同じペースで、gc()の後にgcを例えば57,127から57,128まで実行します。
あなたのデザインは根本的な再作業、おそらくスライディングウィンドウアプローチを必要とします。
コマンドラインからGCを起動できます。これはbatch/crontabには便利です。
jdk1.7.0/bin/jcmd <pid> GC.run
見る :
JVMの仕様では、ガベージコレクションに関して具体的なことは何も述べられていません。このため、ベンダはGCを自由に実装することができます。
そのため、このあいまいさはガベージコレクションの動作に不確実性をもたらします。あなたのJVMの詳細をチェックして、ガベージコレクションのアプローチやアルゴリズムについて知るべきです。また、動作をカスタマイズするためのオプションもあります。
ガベージコレクションを強制する必要がある場合は、おそらくリソースの管理方法を検討する必要があります。あなたはメモリ内に存続する大きなオブジェクトを作成していますか? Disposable
インターフェースを持つラージオブジェクト(グラフィックスクラスなど)を作成し、それを使用したときにdispose()
を呼び出さないでください単一のメソッド内で必要なだけのものをクラスレベルで宣言していますか?
あなたがガベージコレクションを必要とする理由を説明した方が良いでしょう。 SWTを使用している場合は、Image
やFont
などのリソースを解放してメモリを解放できます。例えば:
Image img = new Image(Display.getDefault(), 16, 16);
img.dispose();
未処分のリソースを判断するためのツールもあります。
メモリが不足してOutOfMemoryException
を取得している場合は、単にJava
ではなくJava -Xms128m -Xmx512m
でプログラムを開始することで、Javaで使用可能なヒープスペースの量を増やすことを試みることができます。これにより、初期ヒープサイズが128Mb、最大512Mbになります。これは、標準の32Mb/128Mbよりはるかに大きいものです。
Runtime.getRuntime().gc()
を使用するか、ユーティリティメソッドSystem.gc()
を使用することができます。注:これらの方法ではGCを保証できません。そしてそれらの範囲は、あなたのアプリケーションでプログラム的に扱うのではなく、JVMに限定されるべきです。
JUnitとSpringを使用している場合は、すべてのテストクラスにこれを追加してみてください。
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
別の選択肢は、新しいオブジェクトを作成しないことです。
Object poolingはJavaにおけるGCの必要性を減らすために廃止されました。
オブジェクトプーリングは、一般的にオブジェクト作成よりも速くはありません(軽量オブジェクトの場合は特に)が、ガベージコレクションよりも速くなります。 10,000個のオブジェクトを作成した場合、各オブジェクトは16バイトでした。それはGCが回収しなければならない160,000バイトです。一方、同時に10,000個すべてを必要としない場合は、オブジェクトをリサイクル/再利用するためのプールを作成できます。これにより、新しいオブジェクトを構築する必要がなくなり、古いオブジェクトをGCする必要がなくなります。
このようなもの(未テスト)。それをスレッドセーフにしたい場合は、LinkedListをConcurrentLinkedQueueに交換することができます。
public abstract class Pool<T> {
private int mApproximateSize;
private LinkedList<T> mPool = new LinkedList<>();
public Pool(int approximateSize) {
mApproximateSize = approximateSize;
}
public T attain() {
T item = mPool.poll();
if (item == null) {
item = newInstance();
}
return item;
}
public void release(T item) {
int approxSize = mPool.size(); // not guaranteed accurate
if (approxSize < mApproximateSize) {
recycle(item);
mPool.add(item);
} else if (approxSize > mApproximateSize) {
decommission(mPool.poll());
}
}
public abstract T newInstance();
public abstract void recycle(T item);
public void decommission(T item) { }
}
(評判ポイントが足りないため、コメントとしてこれを追加できません。申し訳ありません。)
私はかつて画像処理会社でJavaの仕事についてインタビューをしました(たとえ私がJavaの経験をほとんど持っていなかったとしても)。
私にとって興味深かった彼らの悲しい話は、彼らのプログラムがイメージのために巨大なバッファを割り当てるということでした。いったん、彼らはイメージと記憶を使い終えたならば、彼らはそれを尊重するでしょう。彼らは本当に遅れるよりも早くメモリを回復する必要が本当にあることを知って、彼らはプログラムの静かな時間の間にJava gc()への明示的な呼び出しを使用しようとしました。残念ながら、gc()は単にJavaランタイムに対する提案であり、効果はありません。
私が思い出したように、彼らは結局自分自身でメモリをリサイクルしなければならなかった。
G1 GCを搭載したOracleJDK 10では、System.gc()
を1回コールすると、GCはOld Collectionをクリーンアップします。 GCがすぐに実行されるかどうかわかりません。ただし、System.gc()
がループ内で何度も呼び出されても、GCはYoungコレクションをクリーンアップしません。 GCにYoungコレクションをクリーンアップさせるには、System.gc()
を呼び出さずにループ(例:new byte[1024]
)で割り当てる必要があります。なんらかの理由でSystem.gc()
を呼び出すと、GCがYoung Collectionをクリーンアップできなくなります。
本当に、私はあなたを迎えません。しかし、 "Infinite Object Creation"をはっきりさせるために、私のビッグシステムには、メモリを処理して生きるオブジェクトを作成するためのコードの一部があることを意味しました。
これは正しいのですが、ジェスチャーだけです。あなたはすでにいくつかのポスターによってすでに与えられた標準的な答えを持っています。これを一つずつ見てみましょう:
実際には、実際のjvmはありません。そのような仕様、望ましい動作を記述した一連のコンピュータサイエンスだけです。あなたが欲しいものを手に入れるために、唯一の方法は積極的な無効化と呼ばれることをすることです。間違った場合の間違いはとても悪いことなので、私たちは自分自身を質問の最初の範囲に限定しなければなりません。
ここのポスターの大部分は、あなたがインタフェースに取り組んでいるとあなたが言っていると仮定するでしょう、そのような場合、あなたがオブジェクト全体または一度に一つのアイテムを手渡されているかどうかを見なければなりません。
オブジェクトが不要になった場合は、そのオブジェクトにnullを代入できますが、誤った場合は、nullポインタ例外が生成されます。 NIOを使えばもっといい仕事ができると思います
あなた、私または他の誰かがいつでも手に入れる: "どうぞ私はそれをひどく必要としてください。"それはあなたが取り組もうとしているもののほぼ完全な破壊のほぼ普遍的な前兆です....使用されている実際のコードをサニタイズして、サンプルコードを表示します。
イライラしないでください。多くの場合、これが解決するのはあなたのdbaがどこかで購入したパッケージを使用していて、オリジナルのデザインが大規模なデータ構造用に調整されていないことです。
それは非常に一般的です。