Apache POI:垃圾回收不会释放内存[Java]

时间:2018-12-14 13:13:15

标签: java excel memory-leaks garbage-collection apache-poi

大家好!

我目前正在使用一种工具,该工具可以使用Apache POI根据给定的规则自动读取excel文件并重组信息。到目前为止,该项目进展顺利,但是我有一个无法解决的问题:

-关闭工作簿后,分配给它的内存不会被垃圾回收。

我已将问题分解成一小段代码来复制该问题。为了便于阅读,我将省略try / catch块:

//the declaration and creation of the objects is seperated due to ommitted try/catch blocks
Workbook wb = null;
FileInputStream fs = null;

//opening filestream and workbook
fs = new FileInputStream("C:/Users/XXX/somefile.xlsm");
wb = WorkbookFactory.create(fs);

//closing them again, making them available for garbage collection
fs.close();
wb.close();

//added to make sure that the reference to the workbook/filestream is null
fs = null;
wb = null;

//added to manually trigger gc in hope that this will fix it
Runtime.getRuntime().gc();

//wait forever for me to check the RAM usage
while(true){Thread.sleep(1000)};

使用POI打开工作簿后,似乎会创建某种缓冲区来填充Xmx参数指定的最大内存量。当我关闭工作簿时,没有释放内存。我还尝试了一个不使用工厂的版本,以检查是否可以通过该模块丢失引用,但是没有运气...

有人可以给我一个提示,为什么不释放内存/收集垃圾吗?

顺便说一句,我正在使用Apache POI 3.17,但是我也测试了4.0(但不是最近发布的4.0.1,tbh ...是的,我是黑客和欺诈^^)

非常感谢!

2 个答案:

答案 0 :(得分:1)

从Runtime.gc()的文档中:

  

运行垃圾收集器。调用此方法建议,Java虚拟机将花费更多精力来回收未使用的对象,以使它们当前占用的内存可用于快速重用。当控制从方法调用返回时,虚拟机将尽最大努力回收所有丢弃的对象。

据我了解,即使您调用Runtime.gc(),JVM也不需要回收任何不需要的东西。

答案 1 :(得分:0)

再见,

我发现:Java只是在减少堆分配方面很懒。由于该软件在很短的时间内仅需要大量内存,因此我设法使用以下JVM参数来驯服该行为:

-Xms32m
-Xmx1g
-XX:+UnlockExperimentalVMOptions
-XX:+UseG1GC 
-XX:MaxHeapFreeRatio=15 
-XX:MinHeapFreeRatio=5

现在,操作完成后将返回内存。

这是我用来弄清楚的资源:

感谢所有贡献者。干杯!