0

我正在使用javax.crypto包来加密/解密文件,但问题是一旦加密了一个大文件(大约 100-700 mb),内存中就会出现 70 Mb(第一次)的峰值,并且在执行后不会释放整个内存完成的。我已经让我的应用程序运行了好几天,但是这个内存没有下降。有趣的是,如果我一次又一次地加密/解密同一个文件,内存不会增加 70 Mb,但是对于前 3-4 次迭代,每次迭代都会释放 5-8 Mb 的内存,之后内存又开始以块的形式增加2-5 Mb,经过几次迭代,一些内存被释放,但所有内存总是增加。
加密文件的代码很简单

 static Cipher c;// = Cipher.getInstance("AES/CBC/PKCS5Padding");
private static void Encrypt_File(String infile, String outFile) throws Exception
{
    //String destKey = "123456";
    //byte[] IV = generateRandomBytes(16);

    //byte[] salt = generateRandomBytes(16);
    //Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes("123456", salt, 1000);
    //SecretKey key = new SecretKeySpec(rfc.getBytes(32), "AES");
    SecretKey key = new SecretKeySpec(generateRandomBytes(32), "AES");
    //if(c == null)
    c = Cipher.getInstance("AES/CBC/PKCS5Padding");

    c.init(Cipher.ENCRYPT_MODE, key);
    FileOutputStream fos = new FileOutputStream(outFile);
    CipherOutputStream cos = new CipherOutputStream(fos, c);
    FileInputStream fis = new FileInputStream(infile);
    try
    {
        int len = 0;
        byte[] buf = new byte[1024*128];
        while((len = fis.read(buf)) != -1) {
            cos.write(buf, 0, len);
            //cos.flush();
        }           
    }
    finally 
    {
        c.doFinal();
        cos.flush();
        cos.close();                
        fos.flush();
        fos.close();
        fis.close();

    }
}

这是我在程序中看到的简单观察:我使用的是 Windows 7 64 位和 16 GB RAM Intel Core 2 Duo 3.00 GHz,加密文件大小为 700 MB。

Explanation                Memory Usage(Shown in Windows Task Manager Private Working Set column)
When program starts                    9924 K
After first iteration of encryption    81,180 K
Second Iteration                       78,254 K
3 Iteration                            74,614 K
4 Iteration                            69,523 K
5 Iteration                            72,256 K
6 Iteration                            70,152 K
7 Iteration                            83,327 K
8 Iteration                            85,613 K
9 Iteration                            95,124 K
10 Iteration                           92,698 K
11 Iteration                           94,670 K

我将迭代保持在 2000 次迭代,观察到相同的模式,最终内存使用量为 184,951 K,调用后System.gc()也没有释放该内存。
可能是什么问题,是CipherOutputStreamCipher类有一些内存泄漏还是我在这里做错了什么?

编辑看到链接(发表在评论中)后,我进行了更改,以便我可以打印 JVM 中的内存使用情况,即在代码中添加这些行

System.out.println("  " +i +" \t\t\t " + ConvertTOMB(Runtime.getRuntime().totalMemory()) +" \t\t "+ ConvertTOMB(Runtime.getRuntime().freeMemory()) +" \t\t "+ ConvertTOMB(  Runtime.getRuntime().totalMemory() -Runtime.getRuntime().freeMemory()) );

在1000次迭代后观察到内存使用量增加,然后没有恢复正常,因为在前几次迭代中,内存使用量为1-5 MB,但在1000 次迭代后,内存消耗从未恢复到个位数,范围为25-225 MB

4

1 回答 1

0

一旦分配了内存,JVM 通常不会将内存返还给操作系统。相反,它将其保留为空闲堆内存,并可以将其用于其他对象。

这意味着,在系统级别上,您只会看到内存使用量增加,直到 JVM 停止。

于 2013-10-04T07:36:12.063 回答