記一次EasyExcel的錯誤使用導致的頻繁FullGC

記一次EasyExcel的錯誤使用導致的頻繁FullGC

      • 一、背景描述
      • 二、場景復現
      • 三、原因分析
      • 四、解決方案
      • 五、思考復盤

一、背景描述

繁忙的校招結束了,美好的大學四年也結束了,作者也有10個月沒有更新了。拿到心儀的offer之后也開始了苦B的打工生活。

最近接到了這樣的一個需求:從大量Excel文件中清洗出來關鍵信息,文件數量很多,數據量也很大。

早就聽說EasyExcel是處理Excel的利器,性能極高的同時還不會出現內存溢出,作者想都沒想就開始用了起來,于是就有了今天這篇文章。。。。

二、場景復現

參照GPT以及一些文檔還有以前的一點點使用經驗,作者寫了這樣一段代碼。

@Component
public class EasyExcelUtil {// 這里開了32個線程@Async("excelExecutor")public void test(String fileName){ExcelReaderBuilder read = EasyExcel.read(fileName);List<Object> objects = read.doReadAllSync();// 其他處理邏輯}
}

觀察了一會日志,發現運行的還挺正常,作者就心滿意足的去寫文檔了,悲劇的是寫完文檔回來發現,GC日志上面瘋狂的FullGC,文件也只處理了一千個左右,當時的心情是極其復雜的,于是就開始了漫長的排查。

三、原因分析

首先觀察日志,這時候有些文件其實還是被處理了的,頻繁的FullGC日志中有一些年輕代是被正常回收了的,但是老年代已經滿了,且無論怎么回收,都不會被回收掉,這時候其實就可以想到一種可能性是有一些不會被FullGC回收的大對象存在。于是我去dump了堆內存圖,老年代的分布大概是這樣的:

在這里插入圖片描述

其中SyncReadListener的對象躲過了所有的FullGC且沒有GC Root,猜測一定是SyncReadListener這個類出現了什么問題,我們先看doReadAllSync()這個方法的源碼

在這里插入圖片描述

可以看到是先注冊了SyncReadListener這個監聽器,然后構造了一個excelReader對象,通過excelReader對excel進行讀取,那為什么SyncReadListener會出現這么多大對象呢,我們看看源碼。

在這里插入圖片描述

SyncReadListener可以將某些數據一條條的塞進去,這里我們合理推測其實就是我們讀取到的數據被傳遞給了監聽器,但是為什么沒有被垃圾回收掉呢?推測問題應該就出現在了ExcelReader這個類。

首先是常量定義和一些讀取的方法。

在這里插入圖片描述

接下來這部分內容就有意思了,也是問題所在。

在這里插入圖片描述

這個類重寫了finalize方法,調用了一次finish()方法,而剛才的代碼中調用的邏輯是這樣的

excelReader.readAll();
excelReader.finish();

具體的邏輯就不細看了,語義上的描述大概是讀取所有的內容,然后手動關閉。

這時候就真相大白了,結合我們的代碼中又添加了@Async注解,場景發生的原因大概是:

多個線程同時讀取到了超大文件,導致在excelReader.readAll()過程中老年代被打滿,老年代已經沒有空間去讀取這幾個超大文件中的內容了,且由于ExcelReader重寫了finalize()方法,并不會進入到GC隊列,這就會導致老年代的占用一直是接近100%,不斷的觸發FullGC,而那些使用年輕代就能進行讀取的小文件就可以正常的進行數據解析,隨后被GC掉。

四、解決方案

學習了官方文檔后,發現作者的場景應該使用這部分邏輯,即繼承AnalysisEventListener,重寫invoke方法,doAfterAllAnalysed()方法,最關鍵的是定義一個沒讀取一部分數據就釋放空間的List,這樣可以實現讀取一部分內容后就釋放內存,不會出現讀取超大文件導致大對象無法回收的問題,也是這個工具類的正確使用方法。

在這里插入圖片描述

五、思考復盤

  1. 選擇某個工具類實現功能的時候一定要充分閱讀文檔,找到自己需要的能力
  2. 學習JVM,這會讓好多排查過程變得非常輕松
  3. 養成閱讀源碼的習慣,快速定位生產中的問題
  4. 學習設計模式,哪怕自己的屎山沒機會通過設計模式重構,也能提高自己閱讀優秀開源組件實現邏輯的能力

最后感慨一下:用EasyExcel這個組件好長時間了,都沒有去探索他的實現邏輯,而且最開始使用EasyExcel真的是覺得他用起來比POI更加的Easy,根本不了解他可以解決內存溢出的問題,更是忽略掉了這個組件的更加牛逼的用途,自己的成長空間還是很大啊。。。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/37931.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/37931.shtml
英文地址,請注明出處:http://en.pswp.cn/web/37931.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python海量數據處理腳本大集合:pyWhat

pyWhat&#xff1a;精簡海聯數據&#xff0c;直達數據弱點要害- 精選真開源&#xff0c;釋放新價值。 概覽 pyWhat是Github社區上一款比較實用的開源Python腳本工具。它能夠快速提取信息中的 IP 地址、郵箱、信用卡、數字貨幣錢包地址、YouTube 視頻等內容。當你遇到了一串莫名…

【golang】go mod私有倉庫配置

文章目錄 Golang版本控制go mod使用私有倉庫(gitlab)依賴設置配置代碼托管站點Go mod尋找代碼倉庫原理使用代理實現代碼托管站點訪問 Golang版本控制 go version v1.22.0 當我們新建一個go項目時&#xff0c;在項目根目錄下執行go mod init可以初始化go.mod文件用于管理包依賴。…

Spring Data與多數據源配置

Spring Data與多數據源配置 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01;今天我們來探討如何在Spring Data中配置和使用多個數據源。 在現代應用程序中&…

計算機相關術語科普之什么叫網關(Gateway)

網關&#xff08;Gateway&#xff09;是一個在計算機網絡中起到關鍵作用的設備或系統&#xff0c;它扮演著網絡間連接器或協議轉換器的角色。 一、定義與功能 1&#xff09;定義&#xff1a; 網關是在不同網絡之間實現互連的復雜設備&#xff0c;僅用于兩個高層協議不同的網…

【PYG】Planetoid中邊存儲的格式,為什么打印前十條邊用edge_index[:, :10]

edge_index 是 PyTorch Geometric 中常用的表示圖邊的張量。它通常是一個形狀為 [2, num_edges] 的二維張量&#xff0c;其中 num_edges 表示圖中邊的數量。每一列表示一條邊&#xff0c;包含兩個節點的索引。 實際上這是COO存儲格式&#xff0c;官方文檔里也有寫&#xff0c;…

Web 品質標準

Web 品質標準 引言 隨著互聯網的快速發展,Web應用已經滲透到我們生活的方方面面。為了確保Web應用的質量,提高用戶體驗,Web品質標準應運而生。這些標準涵蓋了多個方面,包括性能、安全性、可訪問性、用戶體驗等。本文將詳細介紹這些標準,并探討它們在實際開發中的應用。 …

上位機圖像處理和嵌入式模塊部署(mcu 項目1:固件編寫)

【 聲明&#xff1a;版權所有&#xff0c;歡迎轉載&#xff0c;請勿用于商業用途。 聯系信箱&#xff1a;feixiaoxing 163.com】 說完了上位機的開發&#xff0c;接下來就是固件的開發。前面我們說過&#xff0c;目前使用的開發板是極海apm32f103的開發板。它自身包含了iap示例…

一些迷你型信息系統

只有一個表&#xff0c;比較簡單易用&#xff1b; 1 博物館信息查詢系統 信息錄入&#xff0c;瀏覽&#xff0c;添加&#xff0c;更新&#xff0c;刪除&#xff1b; 下載&#xff0c; https://download.csdn.net/download/bcbobo21cn/89505217

中國網絡安全審查認證和市場監管大數據中心數據合規官CCRC-DCO

關于CCRC-DCO證書的頒發機構&#xff0c;它是由中國網絡安全審查認證與市場監管大數據中心&#xff08;簡稱CCRC&#xff09;負責。 該中心在2006年得到中央機構編制委員會辦公室的批準成立&#xff0c;隸屬于國家市場監督管理總局&#xff0c;是其直轄的事業單位。 依據《網絡…

計算機的錯誤計算(十八)

摘要 計算機的錯誤計算&#xff08;四&#xff09;指出一元二次方程的計算精度問題。本節給出其一種解決方案。 計算機的錯誤計算&#xff08;四&#xff09;與&#xff08;十七&#xff09;分別指出一元二次方程的求解是具有挑戰性的難題&#xff0c;其出錯原因是因為相減相消…

YOLOv10(7):YOLOv10訓練(以訓練VOC數據集為例)

YOLOv10&#xff08;1&#xff09;&#xff1a;初探&#xff0c;訓練自己的數據_yolov10 訓練-CSDN博客 YOLOv10&#xff08;2&#xff09;&#xff1a;網絡結構及其檢測模型代碼部分閱讀_yolov10網絡結構圖-CSDN博客 YOLOv10&#xff08;4&#xff09;&#xff1a;損失&…

汽車之家論壇評論全面采集實戰指南:Python爬蟲篇

聚焦汽車之家&#xff0c;解鎖評論寶藏 在這個數據為王的時代&#xff0c;每一個角落的信息都可能成為寶貴的洞察來源。汽車之家&#xff0c;作為汽車行業內的權威論壇&#xff0c;其海量的用戶評論不僅是消費者購車的重要參考&#xff0c;也是汽車品牌與市場研究者不可忽視的…

【Android面試八股文】在你之前的Android項目中,你是如何進行性能優化的?

在之前的Android項目中,優化和提升性能是一個重要且常見的任務。 以下是一些常用的性能優化方法和策略: 分析和測量: 使用Android Studio中的Profiling工具(如Profiler、Trace等)進行性能分析,識別CPU、內存和網絡使用情況。使用第三方工具(如Systrace)來分析系統層面…

iOS 練習項目 Landmarks (四):添加 AutoLayout 約束

iOS 練習項目 Landmarks &#xff08;四&#xff09;&#xff1a;添加 AutoLayout 約束 iOS 練習項目 Landmarks &#xff08;四&#xff09;&#xff1a;添加 AutoLayout 約束新增 topLabel圖片視圖圓形裁切陰影使用 AutoLayout 為詳情頁的組件添加約束DetailViewControllerDe…

如何在 Logback 和 Log4j 中獲取日志:一個開發者指南

日志記錄是軟件開發中的關鍵實踐&#xff0c;它幫助我們監控應用程序的行為&#xff0c;定位問題并優化性能。在 Java 生態系統中&#xff0c;Logback 和 Log4j 是兩個廣泛使用的日志框架&#xff0c;它們都基于 SLF4J API 提供日志服務。本文將指導你如何在這兩個框架中獲取日…

7-490 將字符串“software“賦給一個字符指針,并從第一個字母開始間隔地輸出該串(簡單字符串)

編程將字符串"software"賦給一個字符指針 然后從第一個字母開始間隔地輸出該串 請用指針法完成。 輸入樣例: 在這里給出一組輸入。例如&#xff1a; 無輸入輸出樣例: 在這里給出相應的輸出。例如&#xff1a; sfwr #include <stdio.h> #include <stri…

Linux環境下快速部署Spring Boot應用:高效命令組合實踐

概要&#xff1a; 本文旨在介紹一種高效的Linux命令組合&#xff0c;用于簡化Spring Boot項目的部署與管理流程。通過結合使用nohup、java -jar、輸出重定向以及進程管理命令&#xff0c;我們能夠實現Spring Boot應用的快速后臺啟動及便捷的進程控制&#xff0c;尤其適合于自動…

什么是 JVM( Java 虛擬機),它在 Java 程序執行中扮演什么角色?

JVM&#xff0c;全稱Java Virtual Machine&#xff0c;中文譯作“Java虛擬機”&#xff0c;它是運行Java程序的軟件環境&#xff0c;也是Java語言的核心部分之一。 想象一下&#xff0c;如果你是一位環球旅行家&#xff0c;每到一個新的國家&#xff0c;都需要學習當地的語言才…

【Linux】初識操作系統

一、馮?諾依曼體系結構 在學習操作系統之前&#xff0c;我們先來認識一下馮?諾依曼體系結構&#xff0c;我們常見的計算機&#xff0c;如筆記本。我們不常見的計算機&#xff0c;如服務器&#xff0c;大部分都遵守馮諾依曼體系。 截至目前&#xff0c;我們所認識的計算機&am…

神經網絡訓練(一):基于殘差連接的圖片分類網絡(ResNet18)

目錄 一、簡介:二、圖片分類網絡1.記載訓練數據(torch自帶的cifa10數據集)2.數據增強3.模型構建4.模型訓練三、完整源碼及文檔一、簡介: 基于殘差連接的圖片分類網絡,本網絡使用ResNet18作為基礎模塊,根據cifa10的特點進行改進網絡,使用交叉熵損失函數和SGD優化器。本網…