天天看點

LINUX類主機JAVA應用程式占用CPU、記憶體過高分析手段

轉載聲明:本文為dba+社群原創文章,轉載必須連同本訂閱号二維碼全文轉載,并注明作者名字及來源:dba+社群(dbaplus)。

做為一個it運維人員,通常在運維過程中會遇到各種各樣的問題,系統問題、應用問題、程式問題,而在這當中必然會涉及到性能問題,當使用者量過大,或者伺服器性能不足以支援大使用者量,但同時又得不到擴容的情況下,進行性能分析,并對系統、應用、程式進行優化則顯得尤為重要,同時也是節省資源的一種必不可少的手段,目前大多數的運維産品都是基于java語言開發的,下面我給大家介紹一下在linux環境下對java的性能分析手段。

1. 應用程式占用資源高問題

目前大部分應用程式采用的是java語言開發,在産品上線使用一段時間後,經常會出現某個java程式占用的cpu,記憶體過高,而且幾乎從不釋放,導緻系統卡頓,使用者使用變慢,如果要恢複,則必須殺掉該程序或重新開機該服務,然後進行此操作時,必定會導緻業務中斷。

程式主要由代碼組成,優化則需要知道是哪段代碼占用資源,并且一個應用占用cpu很高,除了确實是計算密集型應用之外,通常原因都是出現了死循環,是以通過優化代碼來降低應用程式的資源消耗或者在應用的使用過程中減少死循環則必不可少。

下面我們以4a平台的字元網關伺服器為例來進行相應分析。

2. 問題分析

2.1. cpu過高分析

1)使用top指令檢視cpu、記憶體使用狀态可以發現cpu占用主要分為兩部分,一部分為系統核心空間占用cpu百分比,一部分為使用者空間占用cpu百分比。其中cpu狀态中标示id的為空閑cpu百分比。當空閑cpu百分比越低,說明cpu占用率越高。

2)初步分析可以發現其中主要占用cpu的程序為java子程序jerryssh服務(使用者通路資源使用的監聽服務),在使用者量不大的情況下,cpu消耗資源很大。根據研發回報字元網關設定的最大通路量可達到500/台,目前字元網關的資源使用現狀無法滿足設定的要求。

● 分析手段

目前針對linux下java程序占用cpu高的分析手段主要為使用linux指令查出高cpu使用的程序,前分析其是由于程序原因還是系統原因,在分析出為程序消耗過高cpu後列出占用cpu高和占用時間最長的線程并使用jdk自帶的jstack工具進行分析cpu使用分析:

export java_home=/usr/apps/java/jdk1.6.0_20/

export path=$java_home/bin:$path

export classpath=.:$java_home/lib/dt.jar:$java_home/lib/tools.jar

分析過程:

根據top指令,發現pid為13033的java程序占用cpu %id 50%以上,占用cpu過高

找到該程序後,首先顯示線程清單,并按照cpu占用高的線程排序:[root@yz-a-zfwg-4 ~]# ps -mp 13033 -o thread,tid,time | sort –rn

顯示結果如下:

LINUX類主機JAVA應用程式占用CPU、記憶體過高分析手段

找到了耗時最高的線程28358,占用cpu時間達8分多鐘。将需要的線程id轉換為16進制格式:[root@yz-a-zfwg-4 ~]# printf "%x\n" 28358

6ec6

最後列印線程的堆棧資訊:

LINUX類主機JAVA應用程式占用CPU、記憶體過高分析手段
LINUX類主機JAVA應用程式占用CPU、記憶體過高分析手段

經比對發現占用cpu高的jerryssh服務中高消耗cpu的代碼均為一些等待和讀取的語句。核心時間占用最長的線程所使用的代碼抓取:

LINUX類主機JAVA應用程式占用CPU、記憶體過高分析手段

2.2. 記憶體使用分析

目前字元網關記憶體使用趨于平衡,除偶爾出現close_wait連接配接後由于未能得到及時釋放而占用了大量記憶體導緻buffers/cache較小外,其他線條暫未出現問題,據研發回報已經做過優化,但是從目前觀察來看coles_wait連接配接釋放時間稍長。并且由于buffers、cached釋放不出來,導緻系統剩餘實體記憶體較小,可能會影響系統性能,為了徹底解決此類問題,是以我們做了以下分析:

LINUX類主機JAVA應用程式占用CPU、記憶體過高分析手段

在linux的記憶體配置設定機制中,系統優先使用實體記憶體,當實體記憶體還有空閑,表示還夠用時,不會釋放其占用記憶體,即使占用記憶體的程式已經被關閉了,該程式所占用的記憶體用來做緩存使用,對于開啟過的程式、或是讀取剛存取過得資料會比較快,是以檢視目前程序正在實際被使用的記憶體(used-buffers-cache),也可以認為如果交換分區(swap)沒有大量使用,實體記憶體(mem)還是夠用的,隻有實體記憶體(mem)被目前程序實際占用完(沒有了buffers和cache),才會使用到交換分區(swap)。

但是從代碼的角度,目前研發人員主要關注java.lang.outofmemoryerror: java heap space異常,減少不必要的對象建立,同時避免記憶體洩漏,是以分析代碼才是我們接下來要做的主要工作;以下為字元網關分析記憶體占用的故障排查過程:

top指令:linux指令。可以檢視實時的記憶體使用情況。  

jmap -histo:live [pid],然後分析具體的對象數目和占用記憶體大小,進而定位代碼。

jmap -dump:live,format=b,file=xxx.xxx [pid],然後利用mat工具分析是否存在記憶體洩漏。

java提供了一個很好的記憶體監控工具:jmap指令

jmap指令有下面幾種常用的用法:

LINUX類主機JAVA應用程式占用CPU、記憶體過高分析手段
LINUX類主機JAVA應用程式占用CPU、記憶體過高分析手段

從上述列印的日志可以得知該程序調系統程序占用記憶體的主要程式。

使用./jmap -histo:live 14978查詢目前 java程序建立的活躍對象數目和占用記憶體大小。

可以日志中發現constmethodklass、methodklass、symbolklass都占用了大量的記憶體,特别是占用了大量記憶體的int數組,需要仔細檢查相關代碼,接下來這些事就可以丢給研發了。

LINUX類主機JAVA應用程式占用CPU、記憶體過高分析手段

3. 總結分析手段

● 分析cpu占用的方法和手段:

top指令:可以檢視實時的cpu使用情況。

ps -ef指令:可以檢視程序以及程序中線程的目前cpu使用情況以及屬于目前狀态的采樣資料。

jstack:java提供的指令。可以檢視某個程序的目前線程棧運作情況。根據這個指令的輸出可以定位某個程序的所有線程的目前運作狀态、運作代碼,以及是否死鎖等等。

pstack:linux指令。可以檢視某個程序的目前線程棧運作情況

● 分析記憶體性能的方法和技巧:

top指令:可以檢視實時的記憶體使用情況。  

jmap -dump:live,format=b,file=xxx.xxx [pid],然後利用mat工具分析是否存在記憶體洩漏等等。

<b></b>

<b>本文來自雲栖社群合作夥伴"dbaplus",原文釋出時間:2015-12-04</b>