某業務系統中,同一天產生多次excel匯出請求,excel資料需要通過查表獲取,由於資料量過大,導致了outofmemoryerror
事先在服務啟動指令碼中已設定oom異常觸發堆快照引數及gc詳情列印引數:-xx:+printgctimestamps -xx:+printheapatgc -xx:+heapdumponoutofmemoryerror,已知為該服務環境分配的jvm記憶體為6g,所以在事故發生後,我們可以得到gc.log和heapdump.hprof檔案來進行分析
通過mat(eclipse memory analyser)分析堆快照
異常執行緒描述
執行緒http-bio-8443-exec-2的retained heap,即持有資源約為3.5g左右,加上jdbc結果集物件、資料庫連線池物件等,佔據6g左右空間,而jvm最大空間為6g,所以oom也是情理之中
占用空間top3物件
執行緒持有的大批量物件
執行緒中存在著海量的cmccustomer物件,每個物件占用1到2k空間,mat還為我們提供了oom時的一些日誌資訊,我們可以查詢一下什麼方法建立了這麼多物件
導致oom的方法:exportexcel方法
cmccustomer物件為cmc下的乙個pojo,那麼我們可以初步推斷:exportexcel方法需要返回乙個excel,excel所需的資料需要在資料庫中查詢業務所需的cmccustomer表資料,但負責此請求的2號執行緒持有的該物件量過大,導致在該方法執行過程中需要分配更多空間時,沒有了足夠空間可以分配,導致了outofmemoryerror
至此,我們通過堆快照分析,得到了"exportexcel方法引起oom"的初步結論,那麼這個方法就是oom的罪魁禍首嗎?現場還有一條gc.log的線索,我們可以通過gc日誌來分析oom的形成原因。
在實時列印的gc日誌中,我們先分析一段事故發生前的gc資訊
catch (exception e) finally { // do somemybatiscursoritemreader注入:mymybatiscursoritemreader.close();
static void testcursor2() {本次事故覆盤結束,解決方案不盡完善,希望對遇到類似問題的同學有所幫助。accsdeviceinfodaoexample accsdeviceinfodaoexample = new accsdeviceinfodaoexample();
param.put("oredcriteria", accsdeviceinfodaoexample.getoredcriteria());
session.select("com.taobao.accs.mass.petadata.dal.sqlmap.
resulthandler() {
@override
public void handleresult(resultcontext resultcontext) {
accsdeviceinfodao accsdeviceinfodao = (accsdeviceinfodao) resultcontext.getresultobject();
system.out.println(resultcontext.getresultcount());
system.out.println(json.tojsonstring(accsdeviceinfodao));
FAQ系列 記憶體溢位案例
在mysql 5.0版本中,主機名長度超過16個字元,如果啟用 統計的話,十有 會出現記憶體溢位問題。其實早在2009年已經發現這個問題了,16 chars href style border 0px vertical align baseline color rgb 159,159,159 fon...
FAQ系列 記憶體溢位案例
在mysql 5.0版本中,主機名長度超過16個字元,如果啟用 統計的話,十有 會出現記憶體溢位問題。其實早在2009年已經發現這個問題了,16 chars href style border 0px vertical align baseline color rgb 159,159,159 fon...
記憶體溢位常見原因分析
記憶體溢位原因 1.記憶體中載入的資料量過於龐大,如一次從資料庫取出過多資料 一般比如資料查詢未做分頁處理 2.集合類中有對物件的引用,使用完後未清空,使得jvm不能 3.中存在死迴圈或迴圈產生過多重複的物件實體 4.使用的第三方軟體中的bug 一般引用第三方jar包過多會出現此類問題 5.啟動引數...