2016-06-13 2 views
0

私のコードは基本的にApache Spark上で動作しており、各コンテナは別々のJVM上で動作します。コンテナには一定のメモリ制限を指定します。私のプログラムでは、コンテナは1つのタスクを正常に終了しますが、別のタスクを実行しようとすると、メモリ制限を超えたとクラッシュします。別々のコンテナでそれぞれのタスクを実行すると、それらは常に正常に動作します。だから、私はコードで把握することができないタスクが終了した後に閉じられていないリソースが残っているように見え、クローズされていないリソースはコンテナのメモリを増加させます。ですから、私の質問は、JVMにすべてのリソースを強制的に閉じるようにJavaに指示する方法があるかどうかです。ガベージコレクションを強制することもできますか?私はこれらの2つのステップを各タスクの最後に実行したいと思います。メモリが不足実行している場合、Javaはごみは収集し、唯一失敗します -Javaのクローズされていないリソースをすべて強制的に閉じる

+1

いいえ、不要なオブジェクトをクリーンアップするためには、実際にプログラムで注意する必要があります。 Javaは、GCに適格なオブジェクトのメモリを解放します(ただし、OutOfMemoryエラーをスローする前にこれを確実に行います)。 – Thilo

+1

OOMを実行して何が残っているのかを確認するために、ヒープメモリダンプを生成するようにJVMを設定することができます。そのための起動フラグがあります。 – Thilo

+0

これらのリソースはあなたのプログラムによってまだ使用されている可能性があるので、一般的には "クローズされていないすべてのリソースを閉じる"ことはできません。 @Thiloが述べたように、実際のリークを分析するためのヒープダンプがおそらく最善の策です。 –

答えて

2

にトライして、リソースを使用することができますこれには時間がかかりすぎる場合。しかし、あなたがそれを記述する方法では、はおそらくリソース(=ファイル、ソケットなど)が開いていませんが、大きなオブジェクト到達可能です。返されたオブジェクトが不要な中間データを参照しておらず、定数以外の値をstatic変数に格納しないようにしてください。

visualvmまたはヒープダンプを生成して、どのオブジェクトがあなたのメモリを奪うかを見つけることができるもの。

私はScalaにこの機能がないことを知っています。しかし、Javaの8はトライして資源として知られている自動閉鎖外部リソースのための優れた機能を持っています。このブロックを出るとき

try(AutoCloseable foo = openSomeResource()) { 
    doSomething(); 
} 

は自動的にどんなに(例えば例外、リターン)、foo.close();を呼び出しません。このパターンに従えば、リソースを開いたままにするのは難しいです。しかし、これはJavaの "リソース"と呼ばれ、これらはAutoCloseableインターフェイスを実装する必要があります。リソースは開かれていませんが、到達可能なオブジェクトがあります。おそらくJava/Scalaのメモリリークをデバッグする方法に関するチュートリアルがたくさんあります。しかし、通常、最初の手順は、ヒープダンプを取得して、どのくらいのメモリを使用しているかを確認することです。特定のツール(例:hprof、JVM組み込み)では、アロケーションサイトに行番号を表示することさえできます。

+0

私は、大きなオブジェクトが静的変数で参照されているか、mainメソッドのどこかで参照されていると考えます。 – slartidan

+0

またはワーカースレッドのスレッドローカルでは? – Det

+0

メソッドが返ってきたときにメインメソッドのものをGCedする必要があります(戻り値から到達可能なものを除いて!)スレッドのローカルに到達できなくなり、スレッドが終了するとGCableになります。私はそれが単にすべての入力データへの参照を保持して戻り値だと思う。 –

0

たぶん、あなたはあなたがSystem.gc();を実行することができますが、私はそれを助けるために起こっている疑いJDK7以上

try (BufferedReader br = new BufferedReader(new FileReader(path))) { 
     return br.readLine(); 
     } 
関連する問題