我正在使用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()
也没有释放该内存。
可能是什么问题,是CipherOutputStream
或Cipher
类有一些内存泄漏还是我在这里做错了什么?
编辑看到链接(发表在评论中)后,我进行了更改,以便我可以打印 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