java加密大文件导致java.lang.OutOfMemoryError:Java堆空间,可能的解决方案

时间:2018-01-05 08:26:39

标签: java aes

我正在编写java程序来加密视频文件,它按预期执行的小视频文件然而当我尝试大约800兆字节的巨大文件时,它会引发异常 java.lang.OutOfMemoryError: Java heap space。 我已经研究了从here获取有关垃圾收集器的更多信息并查看类似问题here的主题。根据最佳选择的答案你怎么能一次加密一个字节&#34 ;:使用块密码加密是由块(AES:16字节)`。 我的源代码的内容

  

main.java

public static void main(String[] args) {
    String key = "Mary has one cat";
    File inputFile = new File("C:\\Users\\xyz\\Music\\test\\-.mp4");
    File encryptedFile = new File("C:\\Users\\xyz\\Music\\test\\-.mp4.encrypted");
    File decryptedFile = new File("C:\\Users\\xyz\\Music\\test\\decrypted.mp4");

    try {
        CryptoUtils.encrypt(key, inputFile, encryptedFile);
        CryptoUtils.decrypt(key, encryptedFile, decryptedFile);
    } catch (CryptoException ex) {
        System.out.println(ex.getMessage());
        ex.printStackTrace();
    }
}
  

CryptoUtils.java

 private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES";

public static void encrypt(String key, File inputFile, File outputFile)
        throws CryptoException {
    doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
}

public static void decrypt(String key, File inputFile, File outputFile)
        throws CryptoException {
    doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
}

private static void doCrypto(int cipherMode, String key, File inputFile,
        File outputFile) throws CryptoException {
    try {
        Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(cipherMode, secretKey);

        FileInputStream inputStream = new FileInputStream(inputFile);
        byte[] inputBytes = new byte[(int) inputFile.length()];
        inputStream.read(inputBytes);

        byte[] outputBytes = cipher.doFinal(inputBytes);

        FileOutputStream outputStream = new FileOutputStream(outputFile);
        outputStream.write(outputBytes);

        inputStream.close();
        outputStream.close();

    } catch (NoSuchPaddingException | NoSuchAlgorithmException
            | InvalidKeyException | BadPaddingException
            | IllegalBlockSizeException | IOException ex) {
        throw new CryptoException("Error encrypting/decrypting file", ex);
    }
}
  

CryptoException.java

public class CryptoException extends Exception {

public CryptoException() {
}

public CryptoException(String message, Throwable throwable) {
    super(message, throwable);
}}

2 个答案:

答案 0 :(得分:3)

我认为您应该考虑使用CipherOutputStream。这样您就不需要将文件加载到内存中了:

https://docs.oracle.com/javase/9/docs/api/javax/crypto/CipherOutputStream.html

答案 1 :(得分:3)

不要一次处理整个文件:使用缓冲区:

try (FileInputStream inputStream = new FileInputStream(inputFile);
        FileOutputStream outputStream = new FileOutputStream(outputFile)) {
    byte[] inputBytes = new byte[4096];
    for (int n = inputStream.read(inputBytes); n > 0; n = inputStream.read(inputBytes)) {
        byte[] outputBytes = cipher.update(inputBytes, 0, n);
        outputStream.write(outputBytes);
    }

    byte[] outputBytes = cipher.doFinal();
    outputStream.write(outputBytes);
}