我有一个Web应用程序,它通过每10秒运行一次调度程序任务将一些PCL文件转换为PDF。每次最多需要来自目录的20个pc文件并将它们转换为pdf。
前几个任务运行良好,但一步一步变慢,突然出现GC overhead limit exceeded
错误消息。
我试图用VisualVM分析这个内存泄漏,这里是来自heapdump的一些输出:
奇怪的是,显示了这么多的字节实例( 3.366.687 !!!)。在应用程序中我也有Streams,我确实检查了所有这些流是否在相关操作完成后关闭。
我在三个方法中使用单个类中的byte: byte [] buf = new byte [1024];
public void initBuf() {
if (buf != null) {
for (int i = 0; i < buf.length; i++) {
buf[i] = (byte) 0x00;
}
pdf_y = PageSize.A4.getHeight();
}
}
public void appendBuf(char ch) {
if (ch == '\n') {
processChunk();
drawChunks();
pdf_newline();
} else if (ch != '\r') {
buf[buf_index++] = (byte) (0xff & ch);
}
}
public void resetBuf() {
for (int i = buf_index; i >= 0; i--) {
buf[i] = (byte) 0x00;
}
buf_index = 0;
}
你建议我去哪儿看看? 如何才能真正识别出哪些代码对此有害?
我无法发布所有代码,因为有更多的类可以执行此转换,但我真的希望您能帮助我一些建议,因为我花了很多时间,但这个内存问题仍然存在。
提前致谢
答案 0 :(得分:2)
您的探查器屏幕截图显示了330万个 java.lang.Byte 实例,而不是 byte [] 。我会在其他地方寻找使用字节(可能包括从字节自动装箱的实例,以将它们插入到集合中)。
我首先怀疑代码的其他部分是将字节或字节实例添加到地图中(作为键或值)并且未能不再需要时删除它们。但这只是基于追踪我自己的一些内存泄漏的猜测。
答案 1 :(得分:1)
查看有关使用堆转储的VisualVM指南:here's Oracle's。
您可能还会查找NetBeans引用,因为组件是相同的,例如How do you find memory leaks using the Netbeans profiler?
您需要知道谁创建或保留对Byte[]
和Byte
的引用。一个攻击计划是检查单个Byte[]
实例(“实例视图”)并查看其引用。 “最近的GC根”选项将显示一个保留延迟Byte[]
的对象路径。