1. 程式人生 > >一個java記憶體洩漏的排查案例

一個java記憶體洩漏的排查案例

這是個比較典型的java記憶體使用問題,定位過程也比較直接,但對新人還是有點參考價值的,所以就紀錄了一下。

下面介紹一下在不瞭解系統程式碼的情況下,如何一步步分析和定位到具體程式碼的排查過程
(以便新人蔘考和自己回顧)

初步的現象

業務系統消費MQ中訊息速度變慢,積壓了200多萬條訊息,通過jstat觀察到業務系統fullgc比較頻繁,到最後乾脆OOM了:

進一步分析

既然知道了記憶體使用存在問題,那麼就要知道是哪些物件佔用了大量記憶體.

很多人都會想到把堆dump下來再用MAT等工具進行分析,但dump堆要花較長的時間,並且檔案巨大,再從伺服器上拖回本地匯入工具,這個過程太折騰不到萬不得已最好別這麼幹。

可以用更輕量級的線上分析,用jmap檢視存活的物件情況(jmap -histo:live [pid]),可以看出HashTable中的元素有5000多萬,佔用記憶體大約1.5G的樣子:

定位到程式碼

現在已經知道了是HashTable的問題,那麼就要定位出什麼程式碼引起的

接下來自然要看看是什麼程式碼往HashTable裡瘋狂的put資料,於是用神器btrace跟蹤Hashtable.put呼叫的堆疊。

首先寫btrace指令碼TracingHashTable.java:

import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

@BTrace
public class TracingHashTable {
        /*指明要檢視的方法,類*/
        @OnMethod(
            clazz="java.util.Hashtable",
            method="put",
            
[email protected]
(Kind.RETURN)) public static void traceExecute(@Self java.util.Hashtable object){ println("呼叫堆疊!!"); jstack(); } }

然後執行:
bin/btrace -cp build 4947 TracingHashTable.java

看到有大量類似下圖的呼叫堆疊

可以看出是在接收到訊息後查詢入庫的程式碼造成的,業務方法呼叫ibatis再到mysql jdbc驅動執行statement時put了大量的屬性到HashTable中。

通過以上排查已基本定位了由那塊程式碼引起的,接下來就是開啟程式碼工程進行白盒化改造了,對相應程式碼進行優化(不在本文範圍內了。幾個圖中的pid不一致就別糾結了,有些是系統重啟過再截圖的).

更多精彩內容請訪問首發部落格http://jenwang.me

進一步交流:

- Email:[email protected]

- 對於本部落格某些話題感興趣,希望進一步交流的,請加 qq 群:2825967

- 更多技術交流分享在圈子「架構雜談」,跟老司機們聊聊網際網路前沿技術、架構、工具、解決方案等

相關推薦

一個java記憶體洩漏排查案例

這是個比較典型的java記憶體使用問題,定位過程也比較直接,但對新人還是有點參考價值的,所以就紀錄了一下。下面介紹一下在不瞭解系統程式碼的情況下,如何一步步分析和定位到具體程式碼的排查過程(以便新人蔘考和自己回顧)初步的現象業務系統消費MQ中訊息速度變慢,積壓了200多萬條訊

一次 Java 記憶體洩漏排查過程,漲姿勢

人人都會犯錯,但一些錯誤是如此的荒謬,我想不通怎麼會有人犯這種錯誤。更沒想到的是,這種事竟發生在了我們身上。當然,這種東西只有事後才能發現真相。接下來,我將講述一系列最近在我們一個應用上犯過的這種錯誤。最有意思的是,一開始的跡象揭示的問題,與實際發生的問題完全不同。 在一個淒涼的午夜 午夜剛過,我就被一條

Node 記憶體洩漏排查案例

## 背景 在阿里雲上看到我運行了一段時間的程式,發現 memory 一項基本是在穩步提升,就知道有記憶體洩漏的情況出現。如下圖 ![](https://img2020.cnblogs.com/blog/625864/202005/625864-20200507223540106-1525574753.p

java記憶體洩漏問題排查(三)

這個系列應該改個名字,叫做java 命令列視窗(執行在windows環境下)突然退出,但是埠號存在,java虛擬機器程序也存在。   昨天出差到客戶現場一番排查。排除了之前的一系列推測(根據程式日誌發現,程式異常退出是有規律的,每3小時一次,在57分異常退出) 記憶體溢位:程式退出後未生

java記憶體洩漏問題排查

      前些日一直在忙效能測試和效能調優,發現效能基本滿足要求了,但是出現一個很詭異的問題,我分配給JVM記憶體10G記憶體系統能夠跑兩天,如果分配2個G記憶體也就跑3個小時,據測試的同事反應在不停的效能測試時系統宕機時間很有規律,而且這個問題持續了有一段時間了,同事也

Java記憶體洩漏案例

1.問題現象 某系統在執行幾天之後,變得非常的慢,所有功能幾乎不能用,偶爾會報OutOfMemory。 2.問題解決過程 注: 系統執行在linux環境文中涉及命令:jps、jstat、jmap命令都在xxx/java/jdk1.5.0_15/bin路徑下,且要

如何排查Java記憶體洩漏?看完我給跪了!

沒有經驗的程式設計師經常認為Java的自動垃圾回收完全使他們免於擔心記憶體管理。這是一個常見的誤解:雖然垃圾收集器做得很好,但即使是最好的程式設計師也完全有可能成為嚴重破壞記憶體洩漏的犧牲品。讓我解釋一下。 當不必要地維護不再需要的物件引用時,會發生記憶體洩漏。這些洩漏很糟糕。首先,當程式消耗越來越多的

java記憶體洩漏記憶體溢位

java記憶體洩漏和記憶體溢位 概念 a)記憶體洩露:被分配物件可達但無用 b)記憶體溢位:無法申請到足夠的記憶體而產生的錯誤 記憶體洩漏場景 a)建立和應用生命週期一樣的單例物件 b)建立匿名內部類的靜態物件 c)未關閉資源 d)長時間存在的集合容器中建立生命週期短

iOS 記憶體洩漏排查方法及原因分析

級別: ★★☆☆☆ 標籤:「iOS」「記憶體洩漏排查」「Leaks工具」 作者: MrLiuQ 審校: QiShare團隊 本文將從以下兩個層面解決iOS記憶體洩漏問題: 記憶體洩漏排查方法(工具) 記憶體洩漏原因分析(解決方案) 在正式開始前,我們

Java 記憶體溢位排查

Java OOM 毫無疑問是開發人員常見並且及其痛恨的問題,但是任何服務的開發都沒法避免 OOM。 因此,OOM 的排查及定位是每個 Java 工程師都必備的技能。 所遇到的問題 在使用 scala 開發的一個 web 服務,在使用者使用中,經常出現: java.lang.

java記憶體洩漏記憶體溢位

記憶體洩漏指你用malloc或new申請了一塊記憶體,但是沒有通過free或delete將記憶體釋放,導致這塊記憶體一直處於佔用狀態。 記憶體溢位指你申請了10個位元組的空間,但是你在這個空間寫入11或以上位元組的資料,就是溢位。 1. 記憶體溢位 out

java記憶體洩漏原理

1. 什麼是記憶體洩漏? 記憶體洩漏的定義:物件已經沒有被應用程式使用,但是垃圾回收器沒辦法移除它們,因為還在被引用著。 要想理解這個定義,我們需要先了解一下物件在記憶體中的狀態。下面的這張圖就解釋了什麼是無用物件以及什麼是未被引用物件。 上面圖中可以看出,裡面有被引用物件和未被引

java記憶體洩漏的分析方法

這幾天,一直在為Java的“記憶體洩露”問題糾結。Java應用程式佔用的記憶體在不斷的、有規律的上漲,最終超過了監控閾值。福爾摩 斯不得不出手了!   記憶體溢位 out of memory,是指程式在申請記憶體時,沒有足夠的記憶體空間供其使用,出現out of memory;比如

記憶體洩漏排查

最近生產環境某專案突然崩潰,檢視堆疊發現虛擬堆已經滿了,檢視配置, jmap -heap [pic] 堆記憶體為2G,理論上應該是夠用的,所以懷疑為記憶體洩漏, 使用 jmap -histo:live [pid] 列印堆中的物件,發現無法列印, 使用 jmap 

【轉】java記憶體洩漏的定位與分析

1、為什麼會發生記憶體洩漏 Java如何檢測內在洩漏呢?我們需要一些工具進行檢測,並發現記憶體洩漏問題,不然很容易發生down機問題。 編寫java程式最為方便的地方就是我們不需要管理記憶體的分配和釋放,一切由jvm來進行處理,當java物件不再被應用時,等到堆記憶體不夠

Java記憶體洩漏問題--java既然存在垃圾回收機制,為什麼還存在記憶體洩漏

1.什麼叫記憶體洩漏? 簡單來說就是一個東西放在記憶體裡的時間太長了,當你的程式都跑完了,它還存在那裡。這時它是白白的佔用了你的記憶體,累積起來佔用的記憶體越來越多……最後就會導致JVM報錯:out of memory。他佔用的是我們的實體記憶體。 2.java記憶體洩漏的根本原因是? 記

Java記憶體洩漏解決方案

記憶體洩露:     是指在程式執行過程中會不斷的分配記憶體空間,那些不再使用的記憶體空間應該即時回收它們,從而保證可以保證系統可以再次使用這些記憶體。如果存在無用的記憶體沒有被收回來,那就是記憶體洩露。  說明: 對於陣列的操作,堆和棧的操作需要慎重的考慮是否存在記憶體洩露

Java記憶體洩漏簡單的分析總結

一、       理解Java記憶體回收機制  Java的記憶體管理就是物件的分配和釋放問題。在Java中,記憶體的分配是由程式完成的,而記憶體的釋放是由垃圾收集器(Garbage Collection,GC)完成的

java記憶體洩漏的定位與分析

1、為什麼會發生記憶體洩漏 Java如何檢測內在洩漏呢?我們需要一些工具進行檢測,並發現記憶體洩漏問題,不然很容易發生down機問題。 編寫java程式最為方便的地方就是我們不需要管理記憶體的分配和釋放,一切由jvm來進行處理,當java物件不再被應用時,等到堆記憶體不夠

java記憶體洩漏分類及避免

要點 記憶體洩露是指程式中間動態分配了記憶體,但在程式結束時沒有釋放這部分記憶體,從而造成那部分記憶體不可用的情況,重啟計算機可以解決,但也有可能再次發生記憶體洩露,記憶體洩露和硬體沒有關係,它是由軟體設計缺陷引起的。 記憶體洩漏可以分為4類: 1) 常發性記憶體洩漏。發生