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

Java文件下載ZIP報(bào)錯(cuò):Out of Memory的問題排查

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

 廢話少說,上干貨??!

項(xiàng)目中下載小文件或者下載成ZIP文件都正常,但下載超過2G的ZIP文件,報(bào)錯(cuò):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();
}

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

一、原因分析

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

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

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

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

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

二、解決方案

采用流式處理:直接從 InputStream 讀取并寫入到 ZipArchiveOutputStream,而不使用 ByteArrayOutputStream。這樣可以避免將整個(gè)文件加載到內(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();
            }
        }
    }

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

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)

原因分析:

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

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

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

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

相關(guān)文章

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

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

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

    Java去掉字符串最后一個(gè)逗號(hào)的方法

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

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

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

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

    這篇文章主要給大家介紹了關(guān)于Java中map和bean互轉(zhuǎn)常用方法的相關(guān)資料,平時(shí)日常Java開發(fā),經(jīng)常會(huì)涉及到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)的問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(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中配置了主機(jī)名,而在/etc/hosts文件中沒有相應(yīng)的配置,本文給大家詳細(xì)講解,需要的朋友可以參考下
    2023-03-03
  • Spring Boot高效數(shù)據(jù)聚合之道深入講解

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

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

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

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

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

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

最新評(píng)論