zoukankan      html  css  js  c++  java
  • ps -mp pid -o THREAD,tid,time;printf "%x " tid;js

    http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/57422.shtml

    原文内容:

    线上 应用开发故障排查之一:高cpu占用

    一个应用开发占用cpu很高,除了确实是计算密集型应用开发之外,通常原因都是出现了死循环。

    (友情提示:本博文章欢迎转载,但请注明出处:hankchen,http://www.blogjava.net/hankchen

    以我们最近出现的一个实际故障为例,介绍怎么定位和解决这类问题。

    clip_image002

    根据top命令,发现pid为28555的java进程占用cpu高达200%,出现故障。

    通过ps aux | grep pid命令,可以进一步确定是tomcat进程出现了问题。但是,怎么定位到具体线程或者代码呢?

    首先显示线程列表:

    ps -mp pid -o thread,tid,time

    1

    找到了耗时最高的线程28802,占用cpu时间快两个小时了!

    其次将需要的线程id转换为16进制格式:

    printf "%x " tid

    2

    最后打印线程的堆栈信息:

    js tack pid |grep tid -a 30

    3

    找到出现问题的代码了!

    现在来分析下具体的代码:shortsocketio.readbytes(shortsocketio.java:106)

    shortsocketio是应用开发封装的一个用短连接socket通信的开发工具类。readbytes函数的代码如下:

    public byte[] readbytes(int length) throws ioexception {

        if ((this.socket == null) || (!this.socket.isconnected())) {

            throw new ioexception("++++ attempting to read from closed socket");

        }

        byte[] result = null;

        bytearrayoutputstream bos = new bytearrayoutputstream();

        if (this.recindex >= length) {

               bos.write(this.recbuf, 0, length);

               byte[] newbuf = new byte[this.recbufsize];

               if (this.recindex > length) {

                   system.arraycopy(this.recbuf, length, newbuf, 0, this.recindex - length);

               }

               this.recbuf = newbuf;

               this.recindex -= length;

        } else {

               int totalread = length;

               if (this.recindex > 0) {

                    totalread -= this.recindex;

                    bos.write(this.recbuf, 0, this.recindex);

                    this.recbuf = new byte[this.recbufsize];

                    this.recindex = 0;

        }

        int readcount = 0;

        while (totalread > 0) {

             if ((readcount = this.in.read(this.recbuf)) > 0) {

                    if (totalread > readcount) {

                          bos.write(this.recbuf, 0, readcount);

                          this.recbuf = new byte[this.recbufsize];

                          this.recindex = 0;

                   } else {

                         bos.write(this.recbuf, 0, totalread);

                         byte[] newbuf = new byte[this.recbufsize];

                         system.arraycopy(this.recbuf, totalread, newbuf, 0, readcount - totalread);

                         this.recbuf = newbuf;

                         this.recindex = (readcount - totalread);

                 }

                 totalread -= readcount;

            }

       }

    }

    问题就出在标红的代码部分。如果this.in.read()返回的数据小于等于0时,循环就一直进行下去了。而这种情况在网络拥塞的时候是可能发生的。

    至于具体怎么修改就看业务逻辑应该怎么对待这种特殊情况了。

    最后,总结下排查cpu故障的开发方法 和技巧有哪些:

    1、top命令:linux命令。可以查看实时的cpu使用情况。也可以查看最近一段时间的cpu使用情况。

    2、ps命令:linux命令。强大的进程状态监控命令。可以查看进程以及进程中线程的当前cpu使用情况。属于当前状态的采样数据。

    3、js tack:java提供的命令。可以查看某个进程的当前线程栈运行情况。根据这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及是否死锁等等。

    4、pstack:linux命令。可以查看某个进程的当前线程栈运行情况。

    (友情提示:本博文章欢迎转载,但请注明出处:hankchen,http://www.blogjava.net/hankchen

    http://binma85.马开东/blog/778986

    开门见山,本文将简述如何使用java thread dump来分析cpu高使用率以及线程死锁问题。 
    一般java thread dump用于web开发中分析web容器或是应用开发服务器开发的性能问题还是比较常用并有效的。常用

     

    此文来自: 马开东博客 转载请注明出处 网址:

    的入门级web容器tomcat,以及高级别的jboss、websphere、weblogic等的性能调优问题都可以使用java thread dump来分析。 
    首先,阐述一下thread dump常用来解决的是何种问题 
    (1)高cpu使用 
    (2)线程死锁 
    其次,使用步骤[以jboss为例] 
    1..get thread dump log 
    (1)找到应用开发程序所在的进程号,命令如下 
    java代码    收藏代码
    1. ps aux |grep 'jboss' | grep 'java'  

    、 
    获取需要的pid 
    (2)执行sudo kill -3 pid获取thread dump log(pid是第一步获取)。 
    注意:在不同的linux环境下执行输出的日志的地方可能不同。在ibm的powerpc小型机上的linux上执行kill -3 pid会在工作目录下产生类似javacore.20100409.161739.7614.0001.txt的文件。jboss默认环境下,thread dump log输出到jboss console,所以thread dump信息会输出到个人定义的控制台打印log中。 
    部分示例如下所以: 

    引用

    2010-10-08 20:27:42 
    full thread dump java hotspot(tm) server vm (16.3-b01 mixed mode): 

    "http-182.50.0.138-8084-6" daemon prio=10 tid=0x08ce5000 nid=0x6a4c in object.wait() [0x87b5c000] 
       java.lang.thread.state: waiting (on object monitor) 
    at java.lang.object.wait(native method) 
    - waiting on <0x95eb81b0> (a org.apache.tomcat.util.net.jioendpoint$worker) 
    at java.lang.object.wait(object.java:485) 
    at org.apache.tomcat.util.net.jioendpoint$worker.await(jioendpoint.java:415) 
    - locked <0x95eb81b0> (a org.apache.tomcat.util.net.jioendpoint$worker) 
    at org.apache.tomcat.util.net.jioendpoint$worker.run(jioendpoint.java:441) 
    at java.lang.thread.run(thread.java:619) 

    "http-182.50.0.138-8084-5" daemon prio=10 tid=0x08c2e000 nid=0x6a4b in object.wait() [0x87bad000] 
       java.lang.thread.state: waiting (on object monitor) 
    at java.lang.object.wait(native method) 
    - waiting on <0x95ed0600> (a org.apache.tomcat.util.net.jioendpoint$worker) 
    at java.lang.object.wait(object.java:485) 
    at org.apache.tomcat.util.net.jioendpoint$worker.await(jioendpoint.java:415) 
    - locked <0x95ed0600> (a org.apache.tomcat.util.net.jioendpoint$worker) 
    at org.apache.tomcat.util.net.jioendpoint$worker.run(jioendpoint.java:441) 
    at java.lang.thread.run(thread.java:619) 

    "ajp-127.0.0.1-8009-acceptor-0" daemon prio=10 tid=0x894de800 nid=0x6a45 runnable [0x881f3000] 
       java.lang.thread.state: runnable 
    at java.net.plainsocketimpl.socketaccept(native method) 
    at java.net.plainsocketimpl.accept(plainsocketimpl.java:390) 
    - locked <0x949c1288> (a java.net.sockssocketimpl) 
    at java.net.serversocket.implaccept(serversocket.java:453) 
    at java.net.serversocket.accept(serversocket.java:421) 
    at org.apache.tomcat.util.net.defaultserversocketfactory.acceptsocket(defaultserversocketfactory.java:61)
    at org.apache.tomcat.util.net.jioendpoint$acceptor.run(jioendpoint.java:309) 
    at java.lang.thread.run(thread.java:619) 

    defaultquartzscheduler_quartzschedulerthread" prio=10 tid=0x8a460800 nid=0x6a38 sleeping[0x88818000] 
       java.lang.thread.state: timed_waiting (sleeping) 
    at java.lang.thread.sleep(native method) 
    at org.quartz.core.quartzschedulerthread.run(quartzschedulerthread.java:394) 



    (3)获取线程信息 
    使用上面的ps或者使用top命令也可以。获取的线程信息如下所示: 

    引用

    27143 root      20   0  780m 376m  11m s   17 11.5   2:56.48 java                                                                   
    4839 root      20   0  778m 162m  11m s   10  5.0   1717:03 java                                                                   
    5049 root      20   0  764m 147m  11m s    4  4.5   1744:06 java                                                                   
        1 root      20   0  2100  720  624 s    0  0.0   0:28.08 init                                                                   
        2 root      15  -5     0    0    0 s    0  0.0   0:00.00 kthreadd                                                               
        3 root      rt  -5     0    0    0 s    0  0.0   0:00.44 migration/0   


    第一列是十进制pid,需要转化为16进制后才能和thread dump信息对应。 
    2.分析thread dump信息[不在列举示例,只讲思想] 
    (1)分析高cpu使用线程的thread dump信息,查找那些代码导致高cpu使用。 
    (2)线程死锁 
        a.为了发现线程动态变化,需要多次做thread dump,每次间隔10-30s为佳. 
        b.线程状态用 runnable(正在运行)、waiting for monitor(主动等待)、waiting for monitor entry(死锁)。所以我们最多的是关注runnable和entry类型的线程。 
    一种典型的死锁是在server端多个应用开发同时使用同一个jboss资源,这时候需要将多个应用开发分不到不用的队列中。

    http://javag.马开东/blog/718243

    参考文献:

    http://www.51testing.com/?uid-188107-action-viewspace-itemid-226468

    1.分析内存的开发工具

    eclipse memory analyzer tool(俗称mat),下载地址为: http://www.eclipse.org/mat/

    使用memory analyzer tool(mat)分析内存泄漏(一)

    使用memory analyzer tool(mat)分析内存泄漏(二)    使用前需要在linux上通过jmap -dump:format=b,file={$filename} ${pid}方式将heap的内存快照文件给dump出来,然后就可以通过上面的mat进行分析了。注意dump出来的文件名要以bin作为后

     

    此文来自: 马开东博客 转载请注明出处 网址:

    缀名不然可能识别不了哦.

    例如: jmap -dump:format=b,file=a.bin 2298

    2.线程状态分析

    "exec-613" id=713 in blocked on lock=com.ss.nio.clientfactory@2262ce5f owned by tomcatthreadpool-exec-553 id=623

    "exec-553" id=623 in timed_waiting on lock=com.ss.nio.abstractrequest@35ce75e at java.lang.object.wait(native method)

    "nioprocessor-1" id=700 in runnable (running in native) at sun.nio.ch.epollarraywrapper.epollwait(native method) at sun.nio.ch.epollarraywrapper.poll(epollarraywrapper.java:215) at sun.nio.ch.epollselectorimpl.doselect(epollselectorimpl.java:65) at sun.nio.ch.selectorimpl.lockanddoselect(selectorimpl.java:69) at sun.nio.ch.selectorimpl.select(selectorimpl.java:80)

    "rmi tcp connection(8)-172.25.3.81" id=698 in runnable at sun.management.threadimpl.getthreadinfo0(native method) at sun.management.threadimpl.getthreadinfo(threadimpl.java:145) at sun.reflect.nativemethodaccessorimpl.invoke0(native method) at sun.reflect.nativemethodaccessorimpl.invoke(nativemethodaccessorimpl.java:39) at sun.reflect.delegatingmethodaccessorimpl.invoke(delegatingmethodaccessorimpl.java:25) at java.lang.reflect.method.invoke(method.java:597)

    runnable(正在运行的,消耗cpu)  timed_waiting(等待被分配到cpu运行的,现在不消耗cpu) blocked(被阻塞,在阻塞解除前不能被分配cpu执行,现在不消耗cpu)

    exec-613占用了锁,exec-553需要的锁被exec-613占用无法执行处于blocked状态.

    nioprocessor-1正在运行,并且他的开发方法 在调用native开发方法 .

    rmi tcp connection(8)-172.25.3.81正在运行.

    (一) jinfo   jinfo打印一个给定的java进程或核心文件或一个远程调试服务器开发的java配置信息。配置信息包括java系统开发属性和jvm命令行标志(更多信息,请参考《jinfo-configuration info》)。   (二) jmap   jmap:如果这个开发工具不使用任何选项(除了pid或core选项)运行,那么它显示类似于solaris的pmap开发工具所输出的信息。这个开发工具支持针对java堆可观察性的若干其它选项。   在java se 6平台中,新加入了一个-dump选项。这样可以使jmap能够把java堆信息复制到一个文件中,然后我们可以使用新的jhat命令(见下面一节)来分析它。   jmap -dump选项并不使用solaris libproc来实现实时处理;而是,它运行当前正运行的jvm中的一小段代码,由此来实现堆复制。既然这种堆复制代码运行于jvm内部,那么其速度是比较快的。堆复制的效果大致相当于实现一次"完全的gc"(对整个堆的垃圾收集),再加上把该堆的内容写入到文件中。实现堆复制的另外一种可能的思路是使用 gcore来进行核心复制并且运行"jmap -dump"(这与以"离线"方式运行的核心复制形成对照)。 

        可以输出某个java进程内存内对象的情况,甚至可以将vm 中的heap,以二进制输出成文本。

  • 相关阅读:
    atitit查询表修改表字段没反应--解锁锁定的表
    atitit.自适应设计悬浮图片的大小and 位置
    .net 科学类型相关问题
    js eval()执行传参函数的写法
    oracle里如何将两个日期的时间差返回**时**分的格式
    .NET开源项目介绍及资源推荐:数据持久层
    highCharts 电流表、电压表
    win7 telnet命令无法使用
    ascx aspx ashx asmx 文件的作用
    Oracle 新建序列值
  • 原文地址:https://www.cnblogs.com/zhoading/p/12481939.html
Copyright © 2011-2022 走看看