使用Sun Java Cryptography Extension(JCE)使用javax.crypto库多次加密/解密大型文件时出现内存问题/泄漏

时间:2013-10-02 11:48:43

标签: java memory memory-management encryption

我正在使用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

1 个答案:

答案 0 :(得分:0)

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

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