大家好!
我目前正在使用一种工具,该工具可以使用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 ...是的,我是黑客和欺诈^^)
非常感谢!
答案 0 :(得分:1)
从Runtime.gc()的文档中:
运行垃圾收集器。调用此方法建议,Java虚拟机将花费更多精力来回收未使用的对象,以使它们当前占用的内存可用于快速重用。当控制从方法调用返回时,虚拟机将尽最大努力回收所有丢弃的对象。
据我了解,即使您调用Runtime.gc()
,JVM也不需要回收任何不需要的东西。
答案 1 :(得分:0)
再见,
我发现:Java只是在减少堆分配方面很懒。由于该软件在很短的时间内仅需要大量内存,因此我设法使用以下JVM参数来驯服该行为:
-Xms32m
-Xmx1g
-XX:+UnlockExperimentalVMOptions
-XX:+UseG1GC
-XX:MaxHeapFreeRatio=15
-XX:MinHeapFreeRatio=5
现在,操作完成后将返回内存。
这是我用来弄清楚的资源:
感谢所有贡献者。干杯!