如何根据这个统计数据改进java代码?

时间:2011-04-19 19:28:50

标签: java performance memory-leaks

我有一个Web应用程序,它通过每10秒运行一次调度程序任务将一些PCL文件转换为PDF。每次最多需要来自目录的20个pc文件并将它们转换为pdf。

前几个任务运行良好,但一步一步变慢,突然出现GC overhead limit exceeded错误消息。

我试图用VisualVM分析这个内存泄漏,这里是来自heapdump的一些输出:enter image description here

奇怪的是,显示了这么多的字节实例 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;
    }

你建议我去哪儿看看? 如何才能真正识别出哪些代码对此有害?

我无法发布所有代码,因为有更多的类可以执行此转换,但我真的希望您能帮助我一些建议,因为我花了很多时间,但这个内存问题仍然存在。

提前致谢

2 个答案:

答案 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[]的对象路径。