欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java文件下載ZIP報錯:Out of Memory的問題排查

 更新時間:2025年01月14日 11:23:11   作者:山林竹筍  
本文主要介紹了Java項目中下載大文件(超過2G的ZIP文件)時出現(xiàn)內(nèi)存溢出(OutOfMemory:JavaHeapSpace)的問題,具有一定的參考價值,感興趣的可以了解一下

 廢話少說,上干貨??!

項目中下載小文件或者下載成ZIP文件都正常,但下載超過2G的ZIP文件,報錯:Out of Memory:Java Heap Space。

內(nèi)存溢出,可是大毛病,排查一下代碼:

 private void setByteArrayOutputStream(String fileName, InputStream inputStream, ZipArchiveOutputStream zous) {
       
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }
        baos.flush();
        byte[] bytes = baos.toByteArray();
        //設(shè)置文件名
        ArchiveEntry entry = new ZipArchiveEntry(fileName);
        zous.putArchiveEntry(entry);
        zous.write(bytes);
        zous.closeArchiveEntry();
        baos.close();
}

細心的童鞋應(yīng)該已經(jīng)發(fā)現(xiàn)錯誤了!

一、原因分析

原因分析主要與 ByteArrayOutputStream 的使用有關(guān)。ByteArrayOutputStream 會在內(nèi)存中動態(tài)擴展其緩沖區(qū)以容納寫入的數(shù)據(jù)。當(dāng)寫入大量數(shù)據(jù)時,尤其是在處理大文件時,可能會導(dǎo)致內(nèi)存頻繁分配和復(fù)制,從而消耗大量內(nèi)存。大文件處理:如果輸入流(InputStream)讀取的數(shù)據(jù)量很大(如超過幾百MB或GB),ByteArrayOutputStream 可能會消耗超過可用內(nèi)存的資源,導(dǎo)致 OutOfMemoryError。

在上述代碼中,邏輯如下:

(1)讀取數(shù)據(jù):通過 inputStream.read(buffer) 持續(xù)將數(shù)據(jù)讀取到緩沖區(qū) buffer 中。

(2)寫入 ByteArrayOutputStream:每次讀取的數(shù)據(jù)都被寫入到 ByteArrayOutputStream 中。如果文件非常大,ByteArrayOutputStream 將不斷擴展其內(nèi)部數(shù)組。

(3) 轉(zhuǎn)換為字節(jié)數(shù)組:調(diào)用 baos.toByteArray() 時,會創(chuàng)建一個新的字節(jié)數(shù)組并將所有數(shù)據(jù)復(fù)制到這個新數(shù)組中,這又需要額外的內(nèi)存。

二、解決方案

采用流式處理:直接從 InputStream 讀取并寫入到 ZipArchiveOutputStream,而不使用 ByteArrayOutputStream。這樣可以避免將整個文件加載到內(nèi)存中。

代碼如下:

?private void setByteArrayOutputStream(String fileName, InputStream inputStream, ZipArchiveOutputStream zous) {
        //創(chuàng)建Zip入口
        try {
            ZipArchiveEntry entry = new ZipArchiveEntry(fileName);
            zous.putArchiveEntry(entry);

            //使用流緩沖區(qū),一次1024字節(jié),分塊讀取并寫入ZIP輸出流
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                zous.write(buffer, 0, len);
            }
            //完成當(dāng)前ZIP入口
            zous.closeArchiveEntry();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            //確保輸入流被關(guān)閉
            try {
                inputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

運行之后,我們發(fā)現(xiàn):不論多大的文件下載,不再報錯內(nèi)存溢出了。但對于超過了4G的文件,在形成ZIP包時,出現(xiàn)了其他錯誤,如下:

org.apache.commons.compress.archivers.zip.Zip64RequiredException: XXXXXXXXXXXXXXXXXXXXXXXXXXXX's size exceeds the limit of 4GByte.
	at org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.checkIfNeedsZip64(ZipArchiveOutputStream.java:651)
	at org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.handleSizesAndCrc(ZipArchiveOutputStream.java:638)
	at org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.closeArchiveEntry(ZipArchiveOutputStream.java:513)

原因分析:

這個異常通常是在嘗試創(chuàng)建一個 ZIP 文件時遇到的,特別是當(dāng)文件的大小超過 4GB 時。ZIP 格式的標(biāo)準(zhǔn)限制了單個文件的大小為 4GB,因此在處理大文件時需要使用 ZIP64 格式。我們在代碼里添加如下:

zous.setUseZip64(ZipArchiveOutputStream.Zip64Mode.Always); // 啟用 ZIP64 支持
或者(不同版本,函數(shù)不一樣)
zous.setUseZip64(Zip64Mode.Always);

按照以上改完之后,我們發(fā)現(xiàn)文件下載ZIP完全沒有內(nèi)存溢出錯誤了。

到此這篇關(guān)于Java文件下載ZIP報錯:Out of Memory的問題排查的文章就介紹到這了,更多相關(guān)Java文件下載ZIP報錯內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java this()和super()的使用注意

    Java this()和super()的使用注意

    這篇文章主要介紹了Java this()和super()的使用注意的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Java去掉字符串最后一個逗號的方法

    Java去掉字符串最后一個逗號的方法

    Java中去掉字符串的最后一個逗號有多種實現(xiàn)方法,不同的方法適用于不同的場景,本文通過實例代碼介紹Java去掉字符串最后一個逗號的相關(guān)知識,感興趣的朋友一起看看吧
    2023-12-12
  • Java中break、continue、return在for循環(huán)中的使用

    Java中break、continue、return在for循環(huán)中的使用

    這篇文章主要介紹了break、continue、return在for循環(huán)中的使用,本文是小編收藏整理的,非常具有參考借鑒價值,需要的朋友可以參考下
    2017-11-11
  • Java?map和bean互轉(zhuǎn)常用的方法總結(jié)

    Java?map和bean互轉(zhuǎn)常用的方法總結(jié)

    這篇文章主要給大家介紹了關(guān)于Java中map和bean互轉(zhuǎn)常用方法的相關(guān)資料,平時日常Java開發(fā),經(jīng)常會涉及到Java?Bean和Map之間的類型轉(zhuǎn)換,需要的朋友可以參考下
    2023-09-09
  • 解決SpringBoot中LocalDateTime返回前端數(shù)據(jù)為數(shù)組結(jié)構(gòu)的問題

    解決SpringBoot中LocalDateTime返回前端數(shù)據(jù)為數(shù)組結(jié)構(gòu)的問題

    本文主要介紹了解決SpringBoot中LocalDateTime返回前端數(shù)據(jù)為數(shù)組結(jié)構(gòu)的問題,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • Java 讀寫鎖源碼分析

    Java 讀寫鎖源碼分析

    這篇文章主要介紹了Java 讀寫鎖的相關(guān)資料,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2021-01-01
  • java.Net.UnknownHostException異常處理問題解決

    java.Net.UnknownHostException異常處理問題解決

    這篇文章主要介紹了java.Net.UnknownHostException異常處理方法,問題原因是在系統(tǒng)的?/etc/Hostname中配置了主機名,而在/etc/hosts文件中沒有相應(yīng)的配置,本文給大家詳細講解,需要的朋友可以參考下
    2023-03-03
  • Spring Boot高效數(shù)據(jù)聚合之道深入講解

    Spring Boot高效數(shù)據(jù)聚合之道深入講解

    這篇文章主要給大家介紹了關(guān)于Spring Boot高效數(shù)據(jù)聚合之道的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • SpringBoot實現(xiàn)對Http接口進行監(jiān)控的代碼

    SpringBoot實現(xiàn)對Http接口進行監(jiān)控的代碼

    Spring Boot Actuator是Spring Boot提供的一個模塊,用于監(jiān)控和管理Spring Boot應(yīng)用程序的運行時信息,本文將介紹一下Spring Boot Actuator以及代碼示例,以及如何進行接口請求監(jiān)控,需要的朋友可以參考下
    2024-07-07
  • Spring+MyBatis實現(xiàn)數(shù)據(jù)庫讀寫分離方案

    Spring+MyBatis實現(xiàn)數(shù)據(jù)庫讀寫分離方案

    本文主要介紹了Spring+MyBatis實現(xiàn)數(shù)據(jù)庫讀寫分離方案。具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01

最新評論