2010-06-01 95 views
4

我在這裏有一種情況,在這裏我們運行一個Java EE服務器並部署了多個應用程序。最近,我們一直頻繁出現OutOfMemoryException異常。我們懷疑某些應用程序可能表現不佳,可能會泄漏,或者其他。內存分析:如何檢測哪個應用程序/軟件包消耗的內存太多

問題是,我們無法確切知道哪一個。我們已經運行了一些內存分析器(比如YourKit),並且他們很擅長告訴哪些類使用最多的內存。但是它們並沒有顯示類之間的關係,所以這給我們留下了這樣的情況:我們看到有很多字符串,int數組和HashMap條目,但是我們無法確切知道它們是哪個應用程序或包來自。

有沒有辦法知道這些對象來自哪裏,所以我們可以嘗試找出分配最多內存的軟件包(或應用程序)?

+0

是否已附上分析器向各個應用?或只是應用程序服務器? – 2010-06-02 00:52:57

+0

你有辦法在測試服務器上分割它們嗎?給每個小堆做個最大堆......然後看看哪個爆炸了? – bwawok 2010-06-02 03:06:26

+0

您還可以啓用GC日誌並查看堆的年輕/舊區域的大小。對於初學者,使用「-verbose:gc -XX:+ PrintGCDetails XX:+ PrintGCTimeStamps -Xloggc:PATH_FROM_ROOT/gclog.log」運行JVM – JoseK 2010-06-02 05:44:49

回答

0

快速的想法是,你也許可以做一些思考,如果你不介意的一些性能權衡....

3

有幾件事情,人們可以在這種情況下做的:

  • Configure the Java EE application server to produce a heap dump on OOME。自1.5天以來,此功能通過JVM參數可用。一旦獲得轉儲,可以使用Eclipse MAT等工具離線分析。重要的部分是找出支配樹。
  • 在測試服務器上執行內存分析; Netbeans擅長這一點。在分析根本原因時,這首先需要更多時間,因爲內存分配失敗的確切條件必須存在。如果您確實有自動化集成/功能測試,那麼推導根本原因將更容易。訣竅是定期進行堆轉儲,並分析導致堆消耗增加的類。可能不一定有泄漏 - 這可能是堆大小不足的情況。
0

我發現有用的是:

jmap -J-d64 -histo $PID 

(除去32位拱-J-d64選項)

這將輸出類似這樣:

num  #instances   #bytes class name 
---------------------------------------------- 
1:  4040792  6446686072 [B 
2:  3420444  1614800480 [C 
3:  3365261  701539904 [I 
4:  7109024  227488768 java.lang.ThreadLocal$ThreadLocalMap$Entry 
5:  6659946  159838704 java.util.concurrent.locks.ReentrantReadWriteLock$Sync$HoldCounter 

而且那麼從那裏你可以嘗試進一步診斷問題,做出差異以及不能比較連續快照。

這隻會暫停虛擬機很短的時間,即使是大堆,所以你可以放心地做在生產(在非高峯時段,希望:))

+0

或者只是運行'jvisualvm',如果你在本地機器上(你不能遠程堆轉儲) – sehugg 2010-10-15 21:27:38