java过度使用内存

时间:2011-06-08 05:50:35

标签: java jvm out-of-memory

在我的一个项目中,我经常压缩很少的数据块。 现在我发现jvm然后增长到6GB的RAM(驻留(RES)RAM,不共享或虚拟等)然后因为内存不足而死亡。 好像垃圾收集器从未运行过。 我已经拿出相关代码并将其粘贴在下面。当我运行它(java6,32位linux)时,它增长到1GB内存。 有人知道如何减少内存使用量吗?

import java.util.Random;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

class test  {
    int blockSize = 4096;
    Random r = new Random();

    public test() throws Exception {
        blockSize = 4096;
        byte [] data = new byte[blockSize];
        for(int index=0; index<blockSize; index++)
            data[index] = (byte)r.nextInt();

        for(long cnt=0; cnt<1000000; cnt++) {
            byte [] result = compress(data);
            if (result != null)
                data[0] = result[0];
        }
    }

    byte [] compress(byte [] in) {
        assert in.length == blockSize;

        Deflater compresser = new Deflater();
        compresser.setInput(in);
        compresser.finish();
        byte [] out = new byte[in.length];
        int outLen = compresser.deflate(out);

        if (outLen < blockSize) {
            byte [] finalOut = new byte[outLen];
            System.arraycopy(out, 0, finalOut, 0, outLen);
            return finalOut;
        }

        return null;
    }

    public static void main(String [] args) throws Exception {
        new test();
    }
}

2 个答案:

答案 0 :(得分:7)

好吧,Folkert van Heusden解决了他自己的问题,但总结一下:

compress(byte [] in) - 方法的早期,我们创建了一个java.util.zip.Deflater

我们使用Deflater做一些事情,然后我们离开compress() - 方法。我们放弃了对deflater - 变量的引用。此时,Deflater已不再使用,正在等待被垃圾收集器杀死。

Deflater分配 Java堆内存 C / C ++ /本机堆内存。由Deflater分配的本机堆内存将一直保留到垃圾收集器调用Deflater.finalize - 方法。如果垃圾收集器运行速度不够快(可能有大量免费的Java堆内存),我们可能会用完C / C ++堆内存。如果发生这种情况,我们将得到“内存不足” - 错误。

Oracle错误报告JDK-4797189可能与此有关。它包含一个代码片段,用于说明和再现问题:

public class Bug {
    public static void main( String args[] ) {
        while ( true ) {
            /* If ANY of these two lines is not commented, the JVM
             runs out of memory */
            final Deflater deflater = new Deflater( 9, true );
            final Inflater inflater = new Inflater( true );
        }
    }
}

解决方案是通过调用Deflater.end()方法(或Inflater.end())来释放资源。

答案 1 :(得分:-1)

好吧,在我看来,代码中没有内存泄漏,所以实际上VM似乎不是GC字节数组。

“任何人都知道如何减少内存使用量?” 好吧,我会试试

byte firstByteOfDataWhichIsCompressedAndThenUncompressed(byte [] in) { ... }

具体返回未压缩数组的第一个字节,而不是整个数组。我知道,这是一个可怕的方法名称,我希望你能找到一个更好的名字。

以下代码

    for(long cnt=0; cnt<1000000; cnt++) {
        byte [] result = compress(data);
        if (result != null)
            data[0] = result[0];
    }

会变成

    for(long cnt=0; cnt<1000000; cnt++)
        data[0] = firstByteOfDataWhichIsCompressedAndThenUncompressed(data);