问题描述
|
我之前也曾问过类似的问题:Java字符串内存泄漏
但是我不确定要问什么:
这是我编写的另一段代码:
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
public class TestString {
public static int readLineXX(BufferedReader br) throws Exception {
String s = br.readLine();
if ( s == null ) return 0;
return 1;
}
public static void main(String args[]) {
while (true) {
try {
FileInputStream fstream = new FileInputStream(\"bigfile.txt\");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while ( readLineXX (br)!= 0) {
//System.out.print(\".\");
}
br.close();
in.close();
fstream.close();
} catch (Exception e) {
}
}
}
}
由于Java中的String是不可变的,因此将“ 1”作为垃圾回收。
我使用-verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails
选项长时间运行了此代码,它运行良好。
这是我的主应用程序的小片段代码,我认为这是泄漏并导致OOM
。
bigfile.txt
在1GB
附近。
解决方法
是的,
s
将被垃圾收集。保持不可变不会阻止其被垃圾回收,而只是防止对其进行修改。
请注意,如果该行很大,则“ 7”可能会占用大量内存。例如,如果您的文本文件是1gb,没有任何换行符,那么br.readLine()
很有可能会消耗2gb,1gb用于读取的数据,然后1gb用于创建的字符串。
,代码中的ѭ9不会导致内存泄漏,因为从ѭ10返回后,它们在任何地方都没有被引用,因此所有垃圾都会被回收。我的怀疑对象是您正在使用的流。我完全可以想象,对于1GB的输入文件,输入流会变得非常大。
一种测试方法是将输入文件切成两部分或更多部分,然后依次读取它们中的每一个。如果罪魁祸首是流,则一个接一个地读取几个较小的输入文件不应导致内存泄漏。
,代替
FileInputStream fstream = new FileInputStream(\"bigfile.txt\");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
你可以用
BufferedReader br = new BufferedReader(new FileReader(\"bigfile.txt\"));
导致OOME的唯一方法是行数非常长且内存有限。您是否正在使用-Xmx选项?为什么使用DataInputStream-是二进制数据还是文本数据?
,代码中没有明显的内存泄漏。
使用-XX:+HeapDumpOnOutOfMemoryError
JVM参数转储堆并分析结果。 (我假设使用Java 6 Hotspot JVM;如果使用的是其他Java JVM,则可能会有类似的选择。)
ѭ14是多余的;流应该在finally块中关闭;但我看不到这种情况如何影响您报告的错误。