web-dev-qa-db-ja.com

Javaでガベージコレクションを強制する方法

たとえややこしくても、Javaでガベージコレクションを強制することは可能ですか?私はSystem.gc();Runtime.gc();について知っていますが、彼らはGCをすることを提案するだけです。どうすればGCを強制できますか?

200
user179172

あなたの最善の選択肢は System.gc() を呼び出すことです。これは単にコレクションを実行したいというガベージコレクタへのヒントです。ガベージコレクタは非決定的なので、強制的におよび即時収集する方法はありません。

154
Andrew Hare

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();
     }
   }
51
shams

GCを強制する(唯一ではないにしても)最善の方法は、カスタムJVMを作成することです。ガベージコレクタはプラグ可能なので、おそらく利用可能な実装の1つを選んでそれを微調整することができます。

注:これは簡単な答えではありません。

41
Mainguy

Java™仮想マシンツールインタフェース(JVM TI) を使用して、関数

jvmtiError ForceGarbageCollection(jvmtiEnv* env)

「VMにガベージコレクションを強制的に実行させます。」 JVM TIは、 JavaTMプラットフォームデバッガアーキテクチャ(JPDA) の一部です。

38
trashgod

YESメソッドを同じ順番で同時に呼び出さなければならないようにすることはほぼ可能です。

System.gc ();
System.runFinalization ();

この2つのメソッドの使用を同時にクリーンアップするためのオブジェクトが1つだけの場合でも、ガベージコレクタは、到達不可能なオブジェクトのfinalise()メソッドを使用して、割り当てられたメモリを解放し、finalize()メソッドの状態を実行します。

しかしながらこれを使うとソフトウェアよりも過負荷になる可能性があるのでガベージコレクタを使うのはひどい習慣です。ガベージコレクタは自分自身のスレッドを持ちます。これは制御することが不可能であり、gcによって使用されるアルゴリズムによっては時間がかかり、非常に非効率的であると考えられます。gcの助けを借りて最悪の場合はあなたのソフトウェアをチェックしてください。 GCに依存します。

注:これは、finalizeメソッドでオブジェクトの再割り当てが行われていない場合にのみ機能します。これが発生した場合、オブジェクトは存続し、技術的に可能な復活が発生します。

24
legramira

OutOfMemoryError のドキュメントでは、VMがフルガベージコレクションの後でメモリの回収に失敗しない限り、スローされないことを宣言しています。したがって、エラーが発生するまでメモリを割り当て続けると、すでにフルガベージコレクションが強制されたことになります。

おそらく、あなたが本当に尋ねたかったのは、「どうすればガベージコレクションで埋め立てるべきだと思うメモリを取り戻すことができるのか」ということでした。

20
Pete Kirkham

手動でGCを要求するには(System.gc()からではありません):

  1. JDKのbinフォルダ(例:C:¥Program Files¥Java¥jdk1.6.0_31¥bin)に移動します。
  2. Jconsole.exeを開く
  3. 目的のローカルプロセスに接続します。
  4. [メモリ]タブに移動し、[GCの実行]をクリックします。
15
Pinkesh Sharma

.gcは将来のリリースでは廃止の候補です。Sunエンジニアはかつてコメントしたところで、世界の20人未満の人々が.gc()の使い方を実際に知っていると述べましたSecureRandomを使用したデータ構造は、40,000オブジェクトを過ぎたところで、vmがポインタを使い果たしたかのように遅くなるデータを生成しました。明らかにそれは16ビットのポインタテーブルをぎゅっとつぶしていて、古典的な「失敗する機械」の振る舞いを示しました。

私は-Xmsなどを試してみましたが、57、xxxになるまで少し動かし続けました。それから、キャンプEasy Moneyでコードが膨大になるのと同じペースで、gc()の後にgcを例えば57,127から57,128まで実行します。

あなたのデザインは根本的な再作業、おそらくスライディングウィンドウアプローチを必要とします。

11
Nicholas Jordan

コマンドラインからGCを起動できます。これはbatch/crontabには便利です。

jdk1.7.0/bin/jcmd <pid> GC.run

見る :

9
guest

JVMの仕様では、ガベージコレクションに関して具体的なことは何も述べられていません。このため、ベンダはGCを自由に実装することができます。

そのため、このあいまいさはガベージコレクションの動作に不確実性をもたらします。あなたのJVMの詳細をチェックして、ガベージコレクションのアプローチやアルゴリズムについて知るべきです。また、動作をカスタマイズするためのオプションもあります。

6
rai.skumar

ガベージコレクションを強制する必要がある場合は、おそらくリソースの管理方法を検討する必要があります。あなたはメモリ内に存続する大きなオブジェクトを作成していますか? Disposableインターフェースを持つラージオブジェクト(グラフィックスクラスなど)を作成し、それを使用したときにdispose()を呼び出さないでください単一のメソッド内で必要なだけのものをクラスレベルで宣言していますか?

4
Bob Kaufman

あなたがガベージコレクションを必要とする理由を説明した方が良いでしょう。 SWTを使用している場合は、ImageFontなどのリソースを解放してメモリを解放できます。例えば:

Image img = new Image(Display.getDefault(), 16, 16);
img.dispose();

未処分のリソースを判断するためのツールもあります。

3
Paul Lammertsma

メモリが不足してOutOfMemoryExceptionを取得している場合は、単にJavaではなくJava -Xms128m -Xmx512mでプログラムを開始することで、Javaで使用可能なヒープスペースの量を増やすことを試みることができます。これにより、初期ヒープサイズが128Mb、最大512Mbになります。これは、標準の32Mb/128Mbよりはるかに大きいものです。

0
Viktor Dahl

Runtime.getRuntime().gc()を使用するか、ユーティリティメソッドSystem.gc()を使用することができます。注:これらの方法ではGCを保証できません。そしてそれらの範囲は、あなたのアプリケーションでプログラム的に扱うのではなく、JVMに限定されるべきです。

0
nabster

JUnitとSpringを使用している場合は、すべてのテストクラスにこれを追加してみてください。

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
0
Aliuk

別の選択肢は、新しいオブジェクトを作成しないことです。

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) { }

}
0
Aaron T Harris

(評判ポイントが足りないため、コメントとしてこれを追加できません。申し訳ありません。)

私はかつて画像処理会社でJavaの仕事についてインタビューをしました(たとえ私がJavaの経験をほとんど持っていなかったとしても)。

私にとって興味深かった彼らの悲しい話は、彼らのプログラムがイメージのために巨大なバッファを割り当てるということでした。いったん、彼らはイメージと記憶を使い終えたならば、彼らはそれを尊重するでしょう。彼らは本当に遅れるよりも早くメモリを回復する必要が本当にあることを知って、彼らはプログラムの静かな時間の間にJava gc()への明示的な呼び出しを使用しようとしました。残念ながら、gc()は単にJavaランタイムに対する提案であり、効果はありません。

私が思い出したように、彼らは結局自分自身でメモリをリサイクルしなければならなかった。

0
Clem Wang

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をクリーンアップできなくなります。

0
Nathan

本当に、私はあなたを迎えません。しかし、 "Infinite Object Creation"をはっきりさせるために、私のビッグシステムには、メモリを処理して生きるオブジェクトを作成するためのコードの一部があることを意味しました。

これは正しいのですが、ジェスチャーだけです。あなたはすでにいくつかのポスターによってすでに与えられた標準的な答えを持っています。これを一つずつ見てみましょう:

  1. 私は実際にこのコードを手に入れることができませんでした

実際には、実際のjvmはありません。そのような仕様、望ましい動作を記述した一連のコンピュータサイエンスだけです。あなたが欲しいものを手に入れるために、唯一の方法は積極的な無効化と呼ばれることをすることです。間違った場合の間違いはとても悪いことなので、私たちは自分自身を質問の最初の範囲に限定しなければなりません。

  1. 私の大規模システムのコードの一部はオブジェクトの作成を行います

ここのポスターの大部分は、あなたがインタフェースに取り組んでいるとあなたが言っていると仮定するでしょう、そのような場合、あなたがオブジェクト全体または一度に一つのアイテムを手渡されているかどうかを見なければなりません。

オブジェクトが不要になった場合は、そのオブジェクトにnullを代入できますが、誤った場合は、nullポインタ例外が生成されます。 NIOを使えばもっといい仕事ができると思います

あなた、私または他の誰かがいつでも手に入れる: "どうぞ私はそれをひどく必要としてください。"それはあなたが取り組もうとしているもののほぼ完全な破壊のほぼ普遍的な前兆です....使用されている実際のコードをサニタイズして、サンプルコードを表示します。

イライラしないでください。多くの場合、これが解決するのはあなたのdbaがどこかで購入したパッケージを使用していて、オリジナルのデザインが大規模なデータ構造用に調整されていないことです。

それは非常に一般的です。

0
Nicholas Jordan