经常有人告诉你流用完要记得关,不然会导致内存泄漏,但你是否考虑过下面这些问题:
这对这些问题,本文就再次对IO流底层工作工作原理展开探讨。
我们首先来一段示例代码,每次请求时就会创建1w个文件输入流,创建完成后并没有关闭,后续我们会通过压测工具请求这个接口。
@RequestMapping("noClose")
public String noClose() throws FileNotFoundException {
//每次请求进来就创建1w次输入文件输入流
for (int i = 0; i < 10000; i++) {
openFileStream();
}
return "success";
}
private static void openFileStream() throws FileNotFoundException {
InputStream is = new FileInputStream("data.txt");
}
为了更快看到效果,我们调整堆内存为50m:
随后我们通过jmeter进行接口压测,不久后问题就出现了:
Exception in thread "RMI TCP Connection(idle)" java.lang.OutOfMemoryError: GC overhead limit exceeded
.....
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
Exception in thread "RMI TCP Connection(idle)" java.lang.OutOfMemoryError: GC overhead limit exceeded
Exception in thread "RMI TCP Connection(idle)" java.lang.OutOfMemoryError: GC overhead limit exceeded
Exception in thread "RMI TCP Connection(idle)" java.lang.OutOfMemoryError: GC overhead limit exceeded
对此我们通过jps定位进程号,然后将内存信息导出:
jmap -dump:live,format=b,file=xxxx.hprof pid
通过mat将导出的xxxx.hprof打开,可以看到排名前3的几个类中包含了File相关,内存泄漏问题很明显是出在我们对文件的操作上。