如何修复 OutOfMemoryError android 工作室

how to fix OutOfMemoryError android studio

我有一个提取 7zip 文件的申请 我将这两个库用于提取

compile 'org.apache.commons:commons-compress:1.12'

compile files('libs/xz-1.3.jar')

这是我的代码

      public void unzip() {
    try  {
        File fc = new File(_location,"Driver2.7z");
        System.out.println("file size"+fc.length());
        //File fd = new File(_location,"Driver2.bin");
        SevenZFile sevenZFile = new SevenZFile(fc);
        SevenZArchiveEntry entry = sevenZFile.getNextEntry();
        System.out.println( "Unzipping " );
        while(entry!=null){
            System.out.println(entry.getName());
            FileOutputStream out = new FileOutputStream(_location + entry.getName());
            //FileOutputStream out = new FileOutputStream(entry.getName());
            System.out.println(entry.getName());
            byte[] content = new byte[(int) entry.getSize()];
            System.out.println(entry.getName());
            sevenZFile.read(content, 0, content.length);
            System.out.println(entry.getName());
            out.write(content);
            System.out.println(entry.getName());
            out.close();
            entry = sevenZFile.getNextEntry();
            System.out.println(entry.getName());
        }
        sevenZFile.close();
   
        Log.d("Unzip", "Unzipping complete. path :  " +_location );
    } catch(Exception e) {
        System.out.println("Decompress"+ "unzip"+ e.getMessage());
    }

}

使用此代码我在某些设备上收到此错误

 E/AndroidRuntime: FATAL EXCEPTION: Thread-218
                                                              Process: ir.milano.driver, PID: 30164
                                                              java.lang.OutOfMemoryError: Failed to allocate a 137881308 byte allocation with 4194304 free bytes and 129MB until OOM
                                                                  at com.darkgamers.pepsiman.browser.mainmenu.DecompressFast.unzip(DecompressFast.java:38)
                                                                  at ir.milano.driver.CopyFiles.run(CopyFiles.java:75)

问题出在这一行

byte[] content = new byte[(int) entry.getSize()];

您正在尝试从 zip 中提取一个大文件,大约 130MB。你不应该通过分配一个大的连续字节块来做到这一点。相反,您应该使用 Streams。

Streams 不会一次打开全部内容,而只是跟踪文件中的一个位置,允许一次只读取文件的一部分。您已经有一个输出流 FileOutputStream 您只需要找到相关的 API 调用来获取输入流并研究从输入流复制到输出。

或者,如果没有提供 Stream API,您可以使用 sevenZFile.read 在多个块中读取和写入,但缓冲区要小得多。

byte[] content = new byte[16 * 1024]; //fixed reasonable size buffer
while((int noBytesRead = sevenZFile.read(content, 0, content.size()) != -1){
   //write the noBytesRead from content into your stream.
}

不要将整个 Zip 条目内容加载到内存中。以块的形式复制内容。 4K 的缓冲区大小 shown 在测试中是有效的。

此外,使用 try-with-resources and enhanced for 循环。

byte[] buffer = new byte[4096];
try (SevenZFile sevenZFile = new SevenZFile(fc)) {
    for (SevenZArchiveEntry entry : sevenZFile.getEntries()) {
        try (FileOutputStream out = new FileOutputStream(_location + entry.getName())) {
            for (int len; (len = sevenZFile.read(buffer)) > 0; ) {
                out.write(buffer, 0, len);
            }
        }
    }
}