# 引言

经常有人告诉你流用完要记得关,不然会导致内存泄漏,但你是否考虑过下面这些问题:

  1. 为什么流不关会导致内存泄漏?
  2. JVM不是有垃圾回收机制吗?这些引用我用完不就变垃圾了为什么不会被回收呢?
  3. 流未关闭除了导致内存泄漏?是否还会引发别的问题?

这对这些问题,本文就再次对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相关,内存泄漏问题很明显是出在我们对文件的操作上。