非常に大きなファイルを読み込み、各行からテキストの一部を抽出しています。しかし、オペレーションの終わりには、私は仕事のためのメモリがほとんど残っていません。ガベージコレクタは、ファイルを読み込んだ後にメモリを解放できないようです。Javaはガベージコレクトメモリではありません
私の質問です:このメモリを解放する方法はありますか?これはJVMのバグですか?
これを実証するためにSSCCEを作成しました。それは1MB(16ビットエンコーディングのためにJavaで2MB)のファイルを読み込み、各行から1文字を抽出します(〜4000行、約8KBにする必要があります)。テストの終わりには、まだ2 MBが完全に使用されています!
初期メモリ使用量:
Allocated: 93847.55 kb
Free: 93357.23 kb
直後(手動ガベージコレクションの前に)ファイルに読み込んだ後:
Allocated: 93847.55 kb
Free: 77613.45 kb (~16mb used)
これは、プログラムがたくさんのを使用しているため、予想されますファイルを読み込むためのリソース。
しかし、私ごみは収集し、すべてではないメモリが解放されます。
Allocated: 93847.55 kb
Free: 91214.78 kb (~2 mb used! That's the entire file!)
私は手動でガベージコレクタを呼び出すと、(いくつかのケースでは、それは怠惰である)あなたに保証を与えるものではありませんことを知っています。しかし、これは私の大規模なアプリケーションで起こっていましたが、ファイルがほとんどすべての利用可能なメモリを使い果たし、残りのプログラムの必要性にもかかわらずメモリが使い果たされるようになりました。この例は、ファイルから読み取った超過データが解放されていないという私の疑いを確認します。ここで
は、テストを生成するためのSSCCEです:
import java.io.*;
import java.util.*;
public class Test {
public static void main(String[] args) throws Throwable {
Runtime rt = Runtime.getRuntime();
double alloc = rt.totalMemory()/1000.0;
double free = rt.freeMemory()/1000.0;
System.out.printf("Allocated: %.2f kb\nFree: %.2f kb\n\n",alloc,free);
Scanner in = new Scanner(new File("my_file.txt"));
ArrayList<String> al = new ArrayList<String>();
while(in.hasNextLine()) {
String s = in.nextLine();
al.add(s.substring(0,1)); // extracts first 1 character
}
alloc = rt.totalMemory()/1000.0;
free = rt.freeMemory()/1000.0;
System.out.printf("Allocated: %.2f kb\nFree: %.2f kb\n\n",alloc,free);
in.close();
System.gc();
alloc = rt.totalMemory()/1000.0;
free = rt.freeMemory()/1000.0;
System.out.printf("Allocated: %.2f kb\nFree: %.2f kb\n\n",alloc,free);
}
}
他に誰もやっていないことが非常に珍しいことをしない限り、「jvm bug」は最初の仮定ではありません。 –
特にgcに関して。 –
どのようにSystem.gc()がすべてのメモリを解放すると思いますか?あなたはまだalの文字列を使用しているので、解放することはできません。 –