大家好!
我目前正在开发一种工具,该工具可以使用 Apache POI 根据一组给定的规则自动读取 excel 文件并重组信息。到目前为止,该项目进展顺利,但我有一个问题无法解决:
- 关闭工作簿后,为其分配的内存不会被垃圾回收。
我已将问题分解为一小段代码来重现该问题。为了可读性,我将省略 try/catch block :
//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... 是的,我是黑客和欺诈 ^^)
非常感谢您!
最佳答案
你好,
我想通了:Java 只是懒惰地减少了堆分配。由于该软件仅在很短的时间内需要大量内存,因此我设法使用以下 JVM 参数来控制这种行为:
-Xms32m
-Xmx1g
-XX:+UnlockExperimentalVMOptions
-XX:+UseG1GC
-XX:MaxHeapFreeRatio=15
-XX:MinHeapFreeRatio=5
现在,内存在操作完成后返回。
以下是我用来解决问题的资源:
- 上面@Amongalen 的评论和相应的链接:Java Memory issue using Apache.POI to read write Excel 非常感谢!
- 这个讨论堆分配优化技巧的德语链接:https://metainformatik.de/al/heap/jvm_freigabe_von_unbenutztem_heapspeicher.html
- 工具https://visualvm.github.io/download.html在运行时检查我的堆内存使用情况
- 这个 stackoverflow 线程讨论了一个非常相似的问题:Eclipse release heap back to system .这个线程帮助我正确地塑造了 JVM args。
感谢所有贡献者。干杯!
关于java - Apache POI : garbage collection does not free memory [Java],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53780497/