最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

 廢話(huà)少說(shuō),上干貨??!

項(xiàng)目中下載小文件或者下載成ZIP文件都正常,但下載超過(guò)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ū)以容納寫(xiě)入的數(shù)據(jù)。當(dāng)寫(xiě)入大量數(shù)據(jù)時(shí),尤其是在處理大文件時(shí),可能會(huì)導(dǎo)致內(nèi)存頻繁分配和復(fù)制,從而消耗大量?jī)?nèi)存。大文件處理:如果輸入流(InputStream)讀取的數(shù)據(jù)量很大(如超過(guò)幾百M(fèi)B或GB),ByteArrayOutputStream 可能會(huì)消耗超過(guò)可用內(nèi)存的資源,導(dǎo)致 OutOfMemoryError。

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

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

(2)寫(xiě)入 ByteArrayOutputStream:每次讀取的數(shù)據(jù)都被寫(xiě)入到 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 讀取并寫(xiě)入到 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é),分塊讀取并寫(xiě)入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ì)于超過(guò)了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)文件的大小超過(guò) 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完全沒(méi)有內(nèi)存溢出錯(cuò)誤了。

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

相關(guān)文章

  • java并發(fā)無(wú)鎖多線(xiàn)程單線(xiàn)程示例詳解

    java并發(fā)無(wú)鎖多線(xiàn)程單線(xiàn)程示例詳解

    這篇文章主要為大家介紹了java并發(fā)無(wú)鎖多線(xiàn)程單線(xiàn)程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 關(guān)于IntelliJ IDEA 打包代碼報(bào)錯(cuò)的問(wèn)題

    關(guān)于IntelliJ IDEA 打包代碼報(bào)錯(cuò)的問(wèn)題

    這篇文章主要介紹了關(guān)于IntelliJ IDEA 打包代碼報(bào)錯(cuò)的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • spring源碼閱讀--aop實(shí)現(xiàn)原理講解

    spring源碼閱讀--aop實(shí)現(xiàn)原理講解

    這篇文章主要介紹了spring源碼閱讀--aop實(shí)現(xiàn)原理講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 詳解MyBatis動(dòng)態(tài)代理機(jī)制

    詳解MyBatis動(dòng)態(tài)代理機(jī)制

    MyBatis的動(dòng)態(tài)代理機(jī)制是其核心特性之一,通過(guò)該機(jī)制,開(kāi)發(fā)者可以專(zhuān)注于定義接口和 SQL 映射,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03
  • 使用kafka-console-consumer.sh不停報(bào)WARN的問(wèn)題及解決

    使用kafka-console-consumer.sh不停報(bào)WARN的問(wèn)題及解決

    這篇文章主要介紹了使用kafka-console-consumer.sh不停報(bào)WARN的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java實(shí)現(xiàn)十秒向MySQL插入百萬(wàn)條數(shù)據(jù)

    Java實(shí)現(xiàn)十秒向MySQL插入百萬(wàn)條數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)十秒向MySQL插入百萬(wàn)條數(shù)據(jù),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定借鑒價(jià)值,需要的可以參考一下
    2022-11-11
  • Java二分查找算法與數(shù)組處理的應(yīng)用實(shí)例

    Java二分查找算法與數(shù)組處理的應(yīng)用實(shí)例

    二分查找法,又叫做折半查找法,它是一種效率較高的查找方法。數(shù)組對(duì)于每一門(mén)編程語(yǔ)言來(lái)說(shuō)都是重要的數(shù)據(jù)結(jié)構(gòu)之一,當(dāng)然不同語(yǔ)言對(duì)數(shù)組的實(shí)現(xiàn)及處理也不盡相同。Java 語(yǔ)言中提供的數(shù)組是用來(lái)存儲(chǔ)固定大小的同類(lèi)型元素
    2022-07-07
  • SpringBoot+EasyExcel實(shí)現(xiàn)自定義復(fù)雜樣式導(dǎo)入導(dǎo)出

    SpringBoot+EasyExcel實(shí)現(xiàn)自定義復(fù)雜樣式導(dǎo)入導(dǎo)出

    這篇文章主要為大家詳細(xì)介紹了SpringBoot如何結(jié)果EasyExcel實(shí)現(xiàn)自定義復(fù)雜樣式導(dǎo)入導(dǎo)出功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2025-07-07
  • Java實(shí)現(xiàn)百萬(wàn)數(shù)據(jù)分批次插入的最佳實(shí)踐分享

    Java實(shí)現(xiàn)百萬(wàn)數(shù)據(jù)分批次插入的最佳實(shí)踐分享

    在當(dāng)今數(shù)據(jù)驅(qū)動(dòng)的應(yīng)用開(kāi)發(fā)中,處理大批量數(shù)據(jù)插入是后端開(kāi)發(fā)人員經(jīng)常面臨的挑戰(zhàn),隨著業(yè)務(wù)規(guī)模的擴(kuò)大,數(shù)據(jù)量呈現(xiàn)爆發(fā)式增長(zhǎng),傳統(tǒng)單條插入方式在面對(duì)百萬(wàn)級(jí)數(shù)據(jù)時(shí)顯得力不從心,所以本文給大家分享了Java實(shí)現(xiàn)百萬(wàn)數(shù)據(jù)分批次插入的最佳實(shí)踐,需要的朋友可以參考下
    2025-07-07
  • Java中自己如何實(shí)現(xiàn)log2(N)

    Java中自己如何實(shí)現(xiàn)log2(N)

    這篇文章主要介紹了Java中自己實(shí)現(xiàn)log2(N)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評(píng)論

额济纳旗| 高州市| 怀宁县| 苏尼特左旗| 浦北县| 阿荣旗| 丁青县| 南阳市| 广平县| 改则县| 长汀县| 石柱| 隆回县| 铁力市| 赫章县| 宜兴市| 家居| 水富县| 长春市| 原平市| 林芝县| 北川| 勃利县| 泰顺县| 邹平县| 凤翔县| 海门市| 玛多县| 盘山县| 德阳市| 九龙县| 伊吾县| 高雄县| 北碚区| 大埔县| 万载县| 连州市| 龙泉市| 巩义市| 浦东新区| 渝中区|