簡體   English   中英

使用Sun Java Cryptography Extension(JCE)使用javax.crypto庫多次加密/解密大文件時的內存問題/泄漏

[英]Memory issues/leaks on encrypting/ decrypting large files multiple times with javax.crypto library using Sun Java Cryptography Extension (JCE)

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

一旦分配了JVM,JVM通常不會將其回贈給OS。 而是將其保留為可用堆內存,並可以將其用於其他對象。

這意味着,在系統級別上,您只會看到內存使用量不斷增加,直到JVM停止為止。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM