パッケージを使用して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回の反復後に観察されたメモリ使用量は増加し、その後正常に戻りませんでした.