java 性能問題排查

cpu佔用率太高

1) 首先能過top查看cpu太高的pid,然後經過ps -ef |grep pid查看進程的詳細信息。html

2) 接着查看每一個線程佔用的cpu佔用率,ps -mp pid -o THREAD,tid,time | sort -rn
或者 經過 top -H -p pidjava

3) 轉換,然後經過比較查看哪一個佔用太高, 其次將須要的線程ID轉換爲16進制格式:printf "%x\n" tid算法

得。數組

4)  jstack pid |grep tid -A 30   ,jstack 能夠查看某個進程的當前線程棧運行狀況。根據這個命令的輸出能夠定位某個進程的全部線程的當前運行狀態、運行代碼,以及是否死鎖等等。服務器

5) 最後就根據獲得的信息分析 代碼,看哪塊會出現問題 。socket

 

實戰

今天出現了一個問題,集成代碼上線後,系統卡死,沒法訪問,初看日誌也沒有問題,然後top查看,cpu果真佔用100%+;工具

然後根據如上操做,找到線程id,然後jstack 查看 ,dump信息以下,原來是syslog 出現了問題。this

Thread 9099: (state = IN_VM)
 - java.net.PlainDatagramSocketImpl.datagramSocketCreate() @bci=0 (Compiled frame; information may be imprecise)
 - java.net.AbstractPlainDatagramSocketImpl.create() @bci=15, line=83 (Compiled frame)
 - java.net.DatagramSocket.createImpl() @bci=61, line=342 (Compiled frame)
 - java.net.DatagramSocket.<init>() @bci=56, line=199 (Compiled frame)
 - UDPTest.send() @bci=31, line=35 (Compiled frame)

原生 系統中是有日誌記錄的,由於項目需求,須要將日誌上報syslog服務器,所以須要在記錄日誌的地方,在調一個syslog的接口,從dump發現,syslog出了問題。可是調用syslog的過程的代碼,沒發現什麼異常。接着咱們就去查看syslog的源碼,發現確實有問題,以下send方法內造成死循環。如今解決方案就明確了。若是在send異常時,var5 並無任何變化。若是socket一直異常,則會無限循環。並無按照設定的值重試。spa

byte var5 = 0;

        while(var5 != -1 && var5 < this.netSyslogConfig.getWriteRetries() + 1) {
            try {
                this.socket.send(var4);
                var5 = -1;
            } catch (IOException var7) {
                if(var5 == this.netSyslogConfig.getWriteRetries() + 1) {
                    throw new SyslogRuntimeException(var7);
                }
            }
        }

內存佔用太高( 堆 )

1)通常內存分析 使用 jdk自帶 的 jmap  jhat  .net

jps -ml //查看pid
jmap -heap 9142  //  打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用狀況.

jmap -histo:live 9142 |head  -n 20

jmap -F -dump:format=b,file=test.bin 14424

jhat test.bin 

訪問 http://localhost:7000

 

也可經過 

2) 設置虛擬機參數爲:-Xmx40m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=E:\Java\dump

而後用 jprofile  工具分析 內存 dump文件

 

 

 

一般咱們在開發中常常遇到的OutOfMemoryError 有 PermGen space(永久代)  Java heap space(堆

Java內存模型是描述Java程序中各變量(實例域、靜態域和數組元素)之間的關係,以及在實際計算機系統中將變量存儲到內存和從內存取出變量這樣的低層細節。

在Java虛擬機中,內存分爲三個代:新生代(New)、老生代(Old)、永久代(Perm)。

(1)新生代New:新建的對象都存放這裏

(2)老生代Old:存放重新生代New中遷移過來的生命週期較久的對象。新生代New和老生代Old共同組成了堆內存。

(3)永久代Perm:是非堆內存的組成部分。主要存放加載的Class類級對象如class自己,method,field等等。

若是出現java.lang.OutOfMemoryError: Java heap space異常,說明Java虛擬機的堆內存不夠。緣由有二:

(1)Java虛擬機的堆內存設置不夠,能夠經過參數-Xms、-Xmx來調整。

(2)代碼中建立了大量大對象,而且長時間不能被垃圾收集器收集(存在被引用)。

若是出現java.lang.OutOfMemoryError: PermGen space,說明是Java虛擬機對永久代Perm內存設置不夠。

通常出現這種狀況,都是程序啓動須要加載大量的第三方jar包。例如:在一個Tomcat下部署了太多的應用。

當遇到  heap space異常,時,要經過分析代碼,減小沒必要要的對象建立,同時避免內存泄漏。

1)top 查看佔用率用的pid

2)    jmap -histo:live [pid] > result.log  ,而後分析具體的對象數目和佔用內存大小,從而定位代碼。

以下 通常佔用較高的 constMethodKlass、methodKlass、constantPoolKlass 這些類信息。而遇到 問題的時候 咱們應該重點分析 數組,集合,類等佔據大量內存的類。

 

http://www.ibm.com/developerworks/cn/java/j-lo-performance-tuning-practice/

http://blog.csdn.net/blade2001/article/details/9066001

http://www.cnblogs.com/chy2055/p/5124040.html

相關文章
相關標籤/搜索