精华内容
下载资源
问答
  • Java线程堆栈信息查看

    万次阅读 2015-12-15 09:55:58
    Linux 下Java程序的线程堆栈查看方法: 第一步:在终端运行Java程序 第二步:通过命令 pidof java 找到已经启动的java进程的ID,选择需要查看的java程序的进程ID 第三步:使用命令 kill -3 打印出java程序的线程堆栈...

    Java线程堆栈信息查看方法(Linux下):

    第一步:在终端运行Java程序
    第二步:通过命令 pidof java 找到已经启动的java进程的ID,选择需要查看的java程序的进程ID
    第三步:使用命令 kill -3 <java进行的 pid> 打印出java程序的线程堆栈信息
    第四步:通常情况下运行的项目可能会比较大,那么这个时候打印的堆栈信息可能会有几千到几万行,为了方便查看,我们往往需要将输出内容进行重定向
    使用linux下的重定向命令方式即可:例如: demo.sh > run.log 2>&1 将输出信息重定向到 run.log中。
    注:在操作系统中,0 1 2分别对应着不同的含义, 如下:
    0 : 标准输入,即:C中的stdin , java中的System.in
    1 : 标准输出, 即:C中的stdout ,java中的System.out
    2 : 错误输出, 即:C中的stderr , java中的System.err


    Demo:

    ----------------------------------------------------------------------------------------------
    Sources Code :
    public class PrintThreadTrace {


        Object obj1 = new Object();
        Object obj2 = new Object();


        public void func1(){
            synchronized (obj1){
                func2();
            }
        }


        public void func2(){
            synchronized (obj2){
                while(true){
                    System.out.print("");
                }
            }
        }


        public static void main(String[] args){
            PrintThreadTrace ptt = new PrintThreadTrace();
            ptt.func1();
        }
    }


    ----------------------------------------------------------------------------------------------------------------
    按照步骤操作后的打印输出信息:


    Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.79-b02 mixed mode):


    "Service Thread" daemon prio=10 tid=0x00007fdc880a9000 nid=0x12a4 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE


    "C2 CompilerThread1" daemon prio=10 tid=0x00007fdc880a7000 nid=0x12a3 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE


    "C2 CompilerThread0" daemon prio=10 tid=0x00007fdc880a4000 nid=0x12a2 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE


    "JDWP Command Reader" daemon prio=10 tid=0x00007fdc50001000 nid=0x1299 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE


    "JDWP Event Helper Thread" daemon prio=10 tid=0x00007fdc880a1800 nid=0x1298 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE


    "JDWP Transport Listener: dt_socket" daemon prio=10 tid=0x00007fdc8809e000 nid=0x1297 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE


    "Signal Dispatcher" daemon prio=10 tid=0x00007fdc88091000 nid=0x1296 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE


    "Finalizer" daemon prio=10 tid=0x00007fdc88071800 nid=0x1295 in Object.wait() [0x00007fdc77ffe000]
       java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000000ecb04858> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
    - locked <0x00000000ecb04858> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)


    "Reference Handler" daemon prio=10 tid=0x00007fdc8806f800 nid=0x1294 in Object.wait() [0x00007fdc7c10b000]
       java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00000000ecb04470> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:503)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
    - locked <0x00000000ecb04470> (a java.lang.ref.Reference$Lock)


    "main" prio=10 tid=0x00007fdc8800b800 nid=0x128e runnable [0x00007fdc8fef7000]
       java.lang.Thread.State: RUNNABLE
    at com.wenchain.study.PrintThreadTrace.func2(PrintThreadTrace.java:20)
    - locked <0x00000000ecc04b20> (a java.lang.Object)
    at com.wenchain.study.PrintThreadTrace.func1(PrintThreadTrace.java:13)
    - locked <0x00000000ecc04b10> (a java.lang.Object)
    at com.wenchain.study.PrintThreadTrace.main(PrintThreadTrace.java:27)


    "VM Thread" prio=10 tid=0x00007fdc8806b000 nid=0x1293 runnable 


    "GC task thread#0 (ParallelGC)" prio=10 tid=0x00007fdc88021000 nid=0x128f runnable 


    "GC task thread#1 (ParallelGC)" prio=10 tid=0x00007fdc88023000 nid=0x1290 runnable 


    "GC task thread#2 (ParallelGC)" prio=10 tid=0x00007fdc88024800 nid=0x1291 runnable 


    "GC task thread#3 (ParallelGC)" prio=10 tid=0x00007fdc88026800 nid=0x1292 runnable 


    "VM Periodic Task Thread" prio=10 tid=0x00007fdc880b3800 nid=0x12a5 waiting on condition 


    JNI global references: 1391


    Heap
     PSYoungGen      total 17920K, used 1270K [0x00000000ecb00000, 0x00000000ede80000, 0x0000000100000000)
      eden space 15872K, 8% used [0x00000000ecb00000,0x00000000ecc3d898,0x00000000eda80000)
      from space 2048K, 0% used [0x00000000edc80000,0x00000000edc80000,0x00000000ede80000)
      to   space 2048K, 0% used [0x00000000eda80000,0x00000000eda80000,0x00000000edc80000)
     ParOldGen       total 39424K, used 0K [0x00000000c6200000, 0x00000000c8880000, 0x00000000ecb00000)
      object space 39424K, 0% used [0x00000000c6200000,0x00000000c6200000,0x00000000c8880000)
     PSPermGen       total 21504K, used 2619K [0x00000000c1000000, 0x00000000c2500000, 0x00000000c6200000)
      object space 21504K, 12% used [0x00000000c1000000,0x00000000c128edd8,0x00000000c2500000)


    ----------------------------------------------------------------------------------------------------------------------------
    上面的信息中包含了当前JVM中所有运行的线程信息,其中在示例中我们启动的线程为main线程,其余的都是JVM自己创建的。
    在打印的信息中,我们可以清楚的看见当前线程的调用上下文,可以很清楚的知道程序的运行情况。
    并且我们在最后面还能看见当前虚拟机中的内存使用情况,青年世代,老年世代的信息等等...


    PS: 在JDK1.5以上,我们可以通过在Java程序中调用Thread.getStackTrace()方法来进行堆栈的自动打印,使得线程堆栈的打印时机可编程控制。
    展开全文
  • 通过ps到java进程号将进程的jstack信息输出。jstack信息是java进程的线程堆栈信息,通过该信息可以分析java的线程阻塞等问题。
  • Jstack查询线程堆栈

    2020-10-18 23:12:57
    Jstack是什么? jstack是java虚拟机自带的一... 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 如果java程序崩溃生成core文件,jstack工

    Jstack是什么?

    jstack是java虚拟机自带的一种堆栈跟踪工具。
    jstack主要用来查看Java线程的调用堆栈的,可以用来分析线程问题(如死锁)。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。

    Jstack分析线程堆栈信息的例子

    如程序中发生这样的死锁问题该如何排查呢?我们可以使用java自带的jstack命令进行排查。
    1、使用jps、ps -ef | grep java查看当前java进程的pid,严重情况下可以使用top命令查看当前系统cpu/内存使用率最高的进程pid。
    top命令这里我们的死锁的pid是:3429,这里程序很简单,虽然程序死锁,没有占用很多资源。

    2、使用top -Hp 3429命令查看进程里面占用最多的资源的线程。
    在这里插入图片描述这里我们看到的占用最多资源的线程是:3440。
    3、使用命令printf “%x\n” 3440 把线程pid转换成16进制数,得到:d70。
    4、使用jstack 3429 | grep -20 d70命令查询该线程阻塞的地方。
    在这里插入图片描述到这里就基本跟踪完毕,去代码所在行看看为什么死锁吧。

    线程状态

    想要通过jstack命令来分析线程的情况的话,首先要知道线程都有哪些状态,下面这些状态是我们使用jstack命令查看线程堆栈信息时可能会看到的线程的几种状态:

    1. NEW,未启动的。不会出现在Dump中。
    2. RUNNABLE,在虚拟机内执行的。
    3. BLOCKED,受阻塞并等待监视器锁。
    4. WATING,无限期等待另一个线程执行特定操作。
    5. TIMED_WATING,有时限的等待另一个线程的特定操作。
    6. TERMINATED,已退出的。

    NEW

    当线程被创建出来还没有被调用start()时候的状态。

    2.2 RUNNABLE

    当线程被调用了start(),且处于等待操作系统分配资源(如CPU)、等待IO连接、正在运行状态,即表示Running状态和Ready状态。注:不一定被调用了start()立刻会改变状态,还有一些准备工作,这个时候的状态是不确定的。

    2.3 BLOCKED

    等待监视锁,这个时候线程被操作系统挂起。当进入synchronized块/方法或者在调用wait()被唤醒/超时之后重新进入synchronized块/方法,锁被其它线程占有,这个时候被操作系统挂起,状态为阻塞状态。阻塞状态的线程,即使调用interrupt()方法也不会改变其状态。

    2.4 WAITING

    无条件等待,当线程调用wait()/join()/LockSupport.park()不加超时时间的方法之后所处的状态,直到另一个线程在这个对象上调用了Object.notify()或Object.notifyAll()方法才能恢复,join()的线程需要特定的线程结束才会执行。如果没有被唤醒或等待的线程没有结束,那么将一直等待,当前状态的线程不会被分配CPU资源和持有锁。

    2.5 TIMED_WAITING

    有条件的等待,当线程调用sleep(睡眠时间)/wait(等待时间)/join(等待时间)/
    LockSupport.parkNanos(等待时间)/LockSupport.parkUntil(等待时间)方法之后所处的状态,在指定的时间没有被唤醒或者等待线程没有结束,会被系统自动唤醒,正常退出。

    2.6 TERMINATED

    执行完了run()方法。其实这只是Java语言级别的一种状态,在操作系统内部可能已经注销了相应的线程,或者将它复用给其他需要使用线程的请求,而在Java语言级别只是通过Java代码看到的线程状态而已。

    (引自:https://blog.csdn.net/shi2huang/article/details/80289155 )

    Monitor

    Monitor其实是一种同步工具,也可以说是一种同步机制。每一个Java对象都有成为Monitor的“潜质”。这是为什么?因为在Java的设计中,每一个对象自打娘胎里出来,就带了一把看不见的锁,通常我们叫“内部锁”,或者“Monitor锁”,或者“Intrinsic lock”。下面这个图,描述了线程和 Monitor之间关系,以及线程的状态转换图:monitor

    1. 进入区(Entrt Set):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则迚入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。
    2. 拥有者(The Owner):表示某一线程成功竞争到对象锁。
    3. 等待区(Wait Set):表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。

    从图中可以看出,一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。

    线程动作

    1. runnable:状态一般为RUNNABLE。
    2. in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。
    3. waiting for monitor entry:进入区等待,状态为BLOCKED。
    4. waiting on condition:等待区等待、被park。
    5. sleeping:休眠的线程,调用了Thread.sleep()。
    runnable

    就算是处在runnable也能是在等待,比如当前线程发送http请求还没回来,线程的状态还是runable。

    Wait on condition

    该状态出现在线程等待某个条件的发生。具体是什么原因,可以结合stacktrace来分析。
    最常见的情况就是线程处于sleep状态,等待被唤醒。
    常见的情况还有等待网络IO:在java引入nio之前,对于每个网络连接,都有一个对应的线程来处理网络的读写操作,即使没有可读写的数据,线程仍然阻塞在读写操作上,这样有可能造成资源浪费,而且给操作系统的线程调度也带来压力。在NewIO里采用了新的机制,编写的服务器程序的性能和可扩展性都得到提高。正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。一种情况是网络非常忙,几乎消耗了所有的带宽,仍然有大量数据等待网络读写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。所以要结合系统的一些性能观察工具来综合分析,比如netstat统计单位时间的发送包的数目,如果很明显超过了所在网络带宽的限制 ; 观察 cpu的利用率,如果系统态的CPU时间,相对于用户态的 CPU时间比例较高;如果程序运行在 Solaris 10平台上,可以用dtrace工具看系统调用的情况,如果观察到read/write的系统调用的次数或者运行时间遥遥领先;这些都指向由于网络带宽所限导致的网络瓶颈。(来自http://www.blogjava.net/jzone/articles/303979.html)

    小结:

    1. 1、线程状态为“waiting for monitor entry”:

    意味着它 在等待进入一个临界区 ,所以它在”Entry Set“队列中等待。 此时线程状态一般都是 Blocked:
    java.lang.Thread.State: BLOCKED (on object monitor)

    1. 2、线程状态为“waiting on condition”:

    说明它在等待另一个条件的发生,来把自己唤醒,或者干脆它是调用了 sleep(N)。 此时线程状态大致为以下几种:
    java.lang.Thread.State: WAITING (parking):一直等那个条件发生;
    java.lang.Thread.State: TIMED_WAITING (parking或sleeping):定时的,那个条件不到来,也将定时唤醒自己。

    1. 3、如果大量线程在“waiting for monitor entry”:

    可能是一个全局锁阻塞住了大量线程。 如果短时间内打印的 thread dump 文件反映,随着时间流逝,waiting for monitor entry 的线程越来越多,没有减少的趋势,可能意味着某些线程在临界区里呆的时间太长了,以至于越来越多新线程迟迟无法进入临界区。

    1. 4、如果大量线程在“waiting on condition”:

    可能是它们又跑去获取第三方资源,尤其是第三方网络资源,迟迟获取不到Response,导致大量线程进入等待状态。所以如果你发现有大量的线程都处在 Wait on condition,从线程堆栈看,正等待网络读写,这可能是一个网络瓶颈的征兆,因为网络阻塞导致线程无法执行。

    1. 线程状态为“in Object.wait()”:

    说明它获得了监视器之后,又调用了 java.lang.Object.wait() 方法。
    每个Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在 “Wait Set”中等待的线程状态是 “in Object.wait()”。当线程获得了 Monitor,如果发现线程继续运行的条件没有满足,它则调用对象(一般就是被 synchronized 的对象)的wait() 方法,放弃了 Monitor,进入 “Wait Set”队列。 此时线程状态大致为以下几种:
    java.lang.Thread.State: TIMED_WAITING (on object monitor);
    java.lang.Thread.State: WAITING (on object monitor);
    一般都是RMI相关线程(RMI、RenewClean、 GC Daemon、RMI Reaper),GC线程(Finalizer),引用对象垃圾回收线程(Reference Handler)等系统线程处于这种状态。

    Java方法状态转换

    1. sleep:进入TIMED_WAITING状态,不出让锁
    2. wait:进入TIMED_WAITING状态,出让锁,并进入对象的等待队列
    3. park:进入WAITING状态,对比wait不需要获得锁就可以让线程WAITING,通过unpark唤醒
    4. interrupt:只是给线程发个信号,如果在wait, sleep会收到exception
    5. yeild:在操作系统层面让线程从Running(已经获得cpu时间片)变成Runnable状态,等待继续被调度。在jvm的线程状态还是RUNNABLE

    调用修饰

    表示线程在方法调用时,额外的重要的操作。线程Dump分析的重要信息。修饰上方的方法调用。

    1. locked <地址> 目标:使用synchronized申请对象锁成功,监视器的拥有者。
    2. waiting to lock <地址> 目标:使用synchronized申请对象锁未成功,在迚入区等待。
    3. waiting on <地址> 目标:使用synchronized申请对象锁成功后,释放锁幵在等待区等待。
    4. parking to wait for <地址> 目标

    下面举几个例子对dump信息进行分析下:

    案例一:RUNNABLE状态,进入run方法之后线程的状态,以及在等待IO的时候,线程的状态。

    //模拟发送http请求
    Socket socket = new Socket();
    socket.connect(new InetSocketAddress(InetAddress.
              getByAddress(new byte[] { (byte) 192, (byte) 168, 1, 14 }), 5678));
    
    "IOThread" #10 prio=5 os_prio=0 tid=0x00000000187c7800 nid=0x8b0 runnable [0x00000000192ee000]
        java.lang.Thread.State: RUNNABLE
    	at java.net.DualStackPlainSocketImpl.connect0(Native Method)
    	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
    	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    	- locked <0x00000000eb6c0fa8> (a java.net.DualStackPlainSocketImpl)
    	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    	at java.net.Socket.connect(Socket.java:589)
    	at java.net.Socket.connect(Socket.java:538)
    	at com.test.threadpool.TestThreadState$IOThread.run(TestThreadState.java:83)
    

    分析:虽然线程处在RUNNABLE的状态,但是还是有可能在等待IO。这样就很浪费CPU资源了,所以在使用线程池处理多线程任务的时候,如果是涉及到数据计算可以考虑使用多线程,如果是每个线程中都有http请求的操作,切不可使用多线程来做,因为网络比较慢,会导致其他线程一直得不到执行,而那边线程数却一直在上涨,最后会导致线程挤压cpu会飚高。

    案例二:BLOCKED状态

    模拟两个线程抢锁,当一个线程抢到锁之后进入sleep,sleep状态下不会释放锁,所以另外一个线程被阻塞。从堆栈信息可以看到,locked和waiting to lock都是同一个对象。

    public static void testBlockedState() {
    		Object lock = new Object();
    		SleepThread t1 = new SleepThread("t1", lock);
    		SleepThread t2 = new SleepThread("t2", lock);
    		t1.start();
    		t2.start();
     
    		try {
    			Thread.sleep(100);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
     
    		System.out.println("Thread t1's state " + t1.getState());
    		System.out.println("Thread t2's state " + t2.getState());
    	}
     
    	static class SleepThread extends Thread {
    		private String name;
    		private Object lock;
     
    		public SleepThread(String name, Object lock) {
    			super(name);
    			this.name = name;
    			this.lock = lock;
    		}
     
    		@Override
    		public void run() {
    			System.out.println("Thread:" + name + " in run.");
     
    			synchronized (lock) {
    				System.out.println("Thread:" + name + " hold the lock.");
     
    				try {
    					Thread.sleep(1000 * 1000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
     
    				System.out.println("Thread:" + name + " return the lock.");
    			}
    		}
    	}
    }
    

    测试结果:

    Thread:t2 in run.
     
    Thread:t1 in run.
     
    Thread:t2 hold the lock.
     
    Thread t1's state BLOCKED
    Thread t2's state TIMED_WAITING
    

    堆栈信息:

    "t2" #11 prio=5 os_prio=0 tid=0x0000000018604800 nid=0x934 waiting on condition [0x000000001920f000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
            at java.lang.Thread.sleep(Native Method)
            at com.test.threadpool.TestThreadState$SleepThread.run(TestThreadState.java:274)
            - locked <0x00000000eb64b910> (a java.lang.Object)
    "t1" #10 prio=5 os_prio=0 tid=0x000000001860b000 nid=0x3528 waiting for monitor entry [0x000000001910f000]
       java.lang.Thread.State: BLOCKED (on object monitor)
            at com.test.threadpool.TestThreadState$SleepThread.run(TestThreadState.java:271)
            - waiting to lock <0x00000000eb64b910> (a java.lang.Object)
    

    分析:T2状态TIMED_WAITING,因为获得了锁,但是却执行了Thread.sleep(1000 * 1000)所以状态是TIMED_WAITING,至于T1,因为没有拿到锁所以处在BLOCKED状态。

    WAITING状态

    调用wait()方法导致的WAITING状态。

     /**
     * 线程调用wait方法,状态变成WAITING。
     */
    public static void testStateWatingByWait() {
    	Object lock = new Object();
    	WaitingThread waitingThread = new WaitingThread("WaitingThread", lock);
    	waitingThread.start();
    
    	try {
    		Thread.sleep(100);
    	} catch (InterruptedException e) {
    		e.printStackTrace();
    	}
    
    	System.out.println("Main thread check the state is " + waitingThread.getState() + "."); // WAITING
    }
    
    static class WaitingThread extends Thread {
    	private int timeout = 0;
    	private Object lock;
    
    	public WaitingThread(String name, Object lock) {
    		this(name, lock, 0);
    	}
    
    	public WaitingThread(String name, Object lock, int timeout) {
    		super(name);
    		this.timeout = timeout;
    		this.lock = lock;
    	}
    
    	@Override
    	public void run() {
    		synchronized (lock) {
    			if (timeout == 0) {
    				try {
    					System.out.println("Try to wait.");
    					lock.wait();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			} else {
    				try {
    					System.out.println("Try to wait in " + timeout + ".");
    					lock.wait(timeout);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    
    		System.out.println("Over thread.");
    	}
    }
    

    测试结果:

    Try to wait.
     
    Main thread check the state is WAITING.
    

    堆栈信息:

    "WaitingThread" #10 prio=5 os_prio=0 tid=0x0000000018dea000 nid=0x1220 in Object.wait() [0x00000000198ee000]
       java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x00000000eb6477e8> (a java.lang.Object)
            at java.lang.Object.wait(Object.java:502)
            at com.test.threadpool.TestThreadState$WaitingThread.run(TestThreadState.java:138)
            - locked <0x00000000eb6477e8> (a java.lang.Object)
    

    分析:WaitingThread线程调用lock.wait();所有处在等待中,且没有指定时间。waiting on <0x00000000eb6477e8> 表示该线程使用synchronized申请对象锁成功,locked <0x00000000eb6477e8> 且成功锁住了对象 <0x00000000eb6477e8>

    调用join()方法导致的WAITING状态

    join()的功能就是让“主线程”等待“子线程”结束之后才能继续运行

     /**
     * 线程调用join方法,状态变成WAITING。
     */
    public static void testStateWatingByJoin() {
    	Object lock = new Object();
    	WaitingThread waitingThread = new WaitingThread("WaitingThread", lock);
    	waitingThread.start();
    	JoinThread joinThread = new JoinThread("JoinThread", waitingThread);
    	joinThread.start();
    	
    	try {
    		Thread.sleep(100);
    	} catch (InterruptedException e) {
    		e.printStackTrace();
    	}
    
    	System.out.println("Main thread check the join thread's state is " + joinThread.getState() + "."); // WAITING
    }
    
    static class JoinThread extends Thread {
    	private int timeout = 0;
    	private Thread thread;
    
    	public JoinThread(String name, Thread thread) {
    		this(name, thread, 0);
    	}
    
    	public JoinThread(String name, Thread thread, int timeout) {
    		super(name);
    		this.timeout = timeout;
    		this.thread = thread;
    	}
    
    	@Override
    	public void run() {
    		if (timeout == 0) {
    			try {
    				System.out.println("Try to join.");
    				thread.join();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		} else {
    			try {
    				System.out.println("Try to join in " + timeout + ".");
    				thread.join(timeout);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    		System.out.println("Over join.");
    	}
    }
    static class WaitingThread extends Thread {
    	private int timeout = 0;
    	private Object lock;
    
    	public WaitingThread(String name, Object lock) {
    		this(name, lock, 0);
    	}
    
    	public WaitingThread(String name, Object lock, int timeout) {
    		super(name);
    		this.timeout = timeout;
    		this.lock = lock;
    	}
    
    	@Override
    	public void run() {
    		synchronized (lock) {
    			if (timeout == 0) {
    				try {
    					System.out.println("Try to wait.");
    					lock.wait();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			} else {
    				try {
    					System.out.println("Try to wait in " + timeout + ".");
    					lock.wait(timeout);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    
    		System.out.println("Over thread.");
    	}
    }
    

    测试结果:

    Try to wait.
     
    Try to join.
     
    Main thread check the state is WAITING
    

    堆栈信息:

    "JoinThread" #11 prio=5 os_prio=0 tid=0x0000000019007000 nid=0x33c0 in Object.wait() [0x0000000019c1f000]
       java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x00000000eb64a498> (a com.test.threadpool.TestThreadState$WaitingThread)
            at java.lang.Thread.join(Thread.java:1252)
            - locked <0x00000000eb64a498> (a com.test.threadpool.TestThreadState$WaitingThread)
            at java.lang.Thread.join(Thread.java:1326)
            at com.test.threadpool.TestThreadState$JoinThread.run(TestThreadState.java:194)
    "WaitingThread" #10 prio=5 os_prio=0 tid=0x0000000019006000 nid=0x35ac in Object.wait() [0x0000000019b1f000]
       java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x00000000eb64a468> (a java.lang.Object)
            at java.lang.Object.wait(Object.java:502)
            at com.test.threadpool.TestThreadState$WaitingThread.run(TestThreadState.java:138)
            - locked <0x00000000eb64a468> (a java.lang.Object)
    

    分析:从打印日志可以看出WaitingThread先得到执行,但是因为该线程有lock.wait();操作,导致线程WaitingThread处在WAITING状态,转而cpu执行权给到了JoinThread,但是JoinThread线程有了thread.join();代码导致它要等待WaitingThread线程执行完才能执行,所有2个线程就这样一直WAITING下去,从堆栈信息

    waiting on <0x00000000eb64a498> (a
    com.test.threadpool.TestThreadState$WaitingThread)

    也可以看出JoinThread在等待WaitingThread执行完。

    调用LockSupport.park方法导致的WAITING状态。

    使用线程池的时候经常会遇到这种状态,当线程池里面的任务都执行完毕,会等待获取任务。这个例子非常典型

    public static void testStateWatingByThreadExecutor() {
    	ExecutorService executeService = Executors.newSingleThreadExecutor();
    	executeService.submit(new Runnable() {
    		@Override
    		public void run() {
    			System.out.println("Over Run.");
    		}
    	});
    
    	try {
    		Thread.sleep(10000);
    	} catch (InterruptedException e) {
    		e.printStackTrace();
    	}
    }
    
    "pool-1-thread-1" #10 prio=5 os_prio=0 tid=0x0000000018f9c000 nid=0x2e88 waiting on condition [0x0000000019aaf000]
       java.lang.Thread.State: WAITING (parking)
            at sun.misc.Unsafe.park(Native Method)
            - parking to wait for  <0x00000000eb64cc30> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
            at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
            at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
            at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
            at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
            at java.lang.Thread.run(Thread.java:748)
    

    分析:因为线程执行完了AQS处在自旋状态,或者无线程可执行就会等待,只有线程池加入了新的线程任务,才会被唤醒。

    TIMED_WAITING状态

    只测试sleep()方法,其余参照WAITING状态

    public static void testSleep() {
    	try {
    		Thread.sleep(1000 * 100);
    	} catch (InterruptedException e) {
    		e.printStackTrace();
    	}
    }
    
    "main" #1 prio=5 os_prio=0 tid=0x0000000004f80800 nid=0x34bc waiting on condition [0x0000000004e7f000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
            at java.lang.Thread.sleep(Native Method)
            at com.test.threadpool.TestThreadState.testSleep(TestThreadState.java:233)
            at com.test.threadpool.TestThreadState.main(TestThreadState.java:53)
    

    进入区等待

    "d&a-3588" daemon waiting for monitor entry [0x000000006e5d5000]
    	java.lang.Thread.State: BLOCKED (on object monitor)
    	at com.jiuqi.dna.bap.authority.service.UserService$LoginHandler.handle()
    	- waiting to lock <0x0000000602f38e90> (a java.lang.Object)
    	at com.jiuqi.dna.bap.authority.service.UserService$LoginHandler.handle()
    

    线程状态BLOCKED,线程动作wait on monitor entry,调用修饰waiting to
    lock总是一起出现。表示在代码级别已经存在冲突的调用。必然有问题的代码,需要尽可能减少其发生。

    同步块阻塞

    一个线程锁住某对象,大量其他线程在该对象上等待。

    "blocker" runnable
    	java.lang.Thread.State: RUNNABLE
    	at com.jiuqi.hcl.javadump.Blocker$1.run(Blocker.java:23)
    	- locked <0x00000000eb8eff68> (a java.lang.Object)
    "blockee-11" waiting for monitor entry
    	java.lang.Thread.State: BLOCKED (on object monitor)
    	at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41)
    	- waiting to lock <0x00000000eb8eff68> (a java.lang.Object)
    "blockee-86" waiting for monitor entry
    	java.lang.Thread.State: BLOCKED (on object monitor)
    	at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41)
    	- waiting to lock <0x00000000eb8eff68> (a java.lang.Object)
    

    持续运行的IO,IO操作是可以以RUNNABLE状态达成阻塞。例如:数据库死锁、网络读写。 格外注意对IO线程的真实状态的分析。 一般来说,被捕捉到RUNNABLE的IO调用,都是有问题的。 以下堆栈显示: 线程状态为RUNNABLE。 调用栈在SocketInputStream、SocketImpl、socketRead0等方法。 调用栈包含了jdbc相关的包。很可能发生了数据库死锁,切记就算状态是RUNNABLE也可能处在阻塞状态

    "d&a-614" daemon prio=6 tid=0x0000000022f1f000 nid=0x37c8 runnable [0x0000000027cbd000]
    	java.lang.Thread.State: RUNNABLE
    	at java.net.SocketInputStream.socketRead0(Native Method)
    	at java.net.SocketInputStream.read(Unknown Source)
    	at oracle.net.ns.Packet.receive(Packet.java:240)
    	at oracle.net.ns.DataPacket.receive(DataPacket.java:92)
    	at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:172)
    	at oracle.net.ns.NetInputStream.read(NetInputStream.java:117)
    	at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1034)
    	at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:588)
    

    分线程调度的休眠

    正常的线程池等待

    "d&a-131" in Object.wait()
    	java.lang.Thread.State: TIMED_WAITING (on object monitor)
    	at java.lang.Object.wait(Native Method)
    	at com.jiuqi.dna.core.impl.WorkingManager.getWorkToDo(WorkingManager.java:322)
    	- locked <0x0000000313f656f8> (a com.jiuqi.dna.core.impl.WorkingThread)
    	at com.jiuqi.dna.core.impl.WorkingThread.run(WorkingThread.java:40)
    

    可疑的线程等待

    "d&a-121" in Object.wait()
    	java.lang.Thread.State: WAITING (on object monitor)
    	at java.lang.Object.wait(Native Method)
    	at java.lang.Object.wait(Object.java:485)
    	at com.jiuqi.dna.core.impl.AcquirableAccessor.exclusive()
    	- locked <0x00000003011678d8> (a com.jiuqi.dna.core.impl.CacheGroup)
    	at com.jiuqi.dna.core.impl.Transaction.lock()
    

    上面dump分析:没有等待时间一直等待下去。

    看下面这个例子:

    public class JStackDemo1 {
        public static void main(String[] args) {
            Thread thread = new Thread(new Thread1());
            thread.start();
        }
    }
    class Thread1 implements Runnable{
        @Override
        public void run() {
            lock.wait();
        }
    }
    

    线程堆栈信息如下:

    "Reference Handler" daemon prio=10 tid=0x00007fbbcc06e000 nid=0x286c in Object.wait() [0x00007fbbc8dfc000]
       java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x0000000783e066e0> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:503)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
        - locked <0x0000000783e066e0> (a java.lang.ref.Reference$Lock)
    

    我们能看到:线程的状态WAITING,线程的当前锁住的资源: <0x0000000783e066e0> 线程当前等待的资源:<0x0000000783e066e0>
    为什么同时锁住和等待是同一个资源:
    线程的执行中,先获得了这个对象的 Monitor(对应于 locked <0x0000000783e066e0>)。当执行到 obj.wait(), 线程即放弃了Monitor的所有权,进入 “wait set”队列(对应于 waiting on <0x0000000783e066e0> )。

    示范一:

    下面这个线程在等待这个锁 0x00000000fe7e3b50,等待进入临界区:

    "RMI TCP Connection(64896)-172.16.52.118" daemon prio=10 tid=0x00000000405a6000 nid=0x68fe waiting for monitor entry [0x00007f2be65a3000]
    	java.lang.Thread.State: BLOCKED (on object monitor)
    	at com.xyz.goods.service.impl.GoodsServiceImpl.findChanellGoodsCountWithCache(GoodsServiceImpl.java:1734)
    	- waiting to lock <0x00000000fe7e3b50> (a java.lang.String)
    

    那么谁持有这个锁呢? 是另一个先调用了findChanellGoodsCountWithCache函数的线程:

    "RMI TCP Connection(64878)-172.16.52.117" daemon prio=10 tid=0x0000000040822000 nid=0x6841 runnable [0x00007f2be76b3000]
    	java.lang.Thread.State: RUNNABLE
    	at java.net.SocketInputStream.socketRead0(Native Method)
    	at java.net.SocketInputStream.read(SocketInputStream.java:129)
    	at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
    	at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
    	at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
    	- locked <0x00000000af4ed638> (a java.io.BufferedInputStream)
    	at org.bson.io.Bits.readFully(Bits.java:35)
    	at org.bson.io.Bits.readFully(Bits.java:28)
    	at com.mongodb.Response.<init>(Response.java:35)
    	at com.mongodb.DBPort.go(DBPort.java:110)
    	- locked <0x00000000af442d48> (a com.mongodb.DBPort)
    	at com.mongodb.DBPort.go(DBPort.java:75)
    	- locked <0x00000000af442d48> (a com.mongodb.DBPort)
    	at com.mongodb.DBPort.call(DBPort.java:65)
    	at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:202)
    	at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:296)
    	at com.mongodb.DB.command(DB.java:152)
    	at com.mongodb.DBCollection.getCount(DBCollection.java:760)
    	at com.mongodb.DBCollection.getCount(DBCollection.java:731)
    	at com.mongodb.DBCollection.count(DBCollection.java:697)
    	at com.xyz.goods.manager.MongodbManager.count(MongodbManager.java:202)
    	at com.xyz.goods.service.impl.GoodsServiceImpl.findChanellGoodsCount(GoodsServiceImpl.java:1787)
    	at com.xyz.goods.service.impl.GoodsServiceImpl.findChanellGoodsCountWithCache(GoodsServiceImpl.java:1739)
    	- locked <0x00000000fe7e3b50> (a java.lang.String)
    

    示范二:

    等待另一个条件发生来将自己唤醒:

    "RMI TCP Connection(idle)" daemon prio=10 tid=0x00007fd50834e800 nid=0x56b2 waiting on condition [0x00007fd4f1a59000]
    	java.lang.Thread.State: TIMED_WAITING (parking)
    	at sun.misc.Unsafe.park(Native Method)
    	- parking to wait for  <0x00000000acd84de8> (a java.util.concurrent.SynchronousQueue$TransferStack)
    	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
    	at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:424)
    	at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:323)
    	at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:874)
    	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:945)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
    	at java.lang.Thread.run(Thread.java:662)
    
    1. 1)“TIMED_WAITING (parking)”中的 timed_waiting
      指等待状态,但这里指定了时间,到达指定的时间后自动退出等待状态;parking指线程处于挂起中。

    2)“waiting on condition”需要与堆栈中的“parking to wait for <0x00000000acd84de8> (a java.util.concurrent.SynchronousQueue$TransferStack)”
    结合来看。首先,本线程肯定是在等待某个条件的发生,来把自己唤醒。其次,SynchronousQueue
    并不是一个队列,只是线程之间移交信息的机制,当我们把一个元素放入到 SynchronousQueue
    中时必须有另一个线程正在等待接受移交的任务,因此这就是本线程在等待的条件。

    示范三:

    "RMI RenewClean-[172.16.50.182:4888]" daemon prio=10 tid=0x0000000040d2c800 nid=0x97e in Object.wait() [0x00007f9ccafd0000]
    	java.lang.Thread.State: TIMED_WAITING (on object monitor)
    	at java.lang.Object.wait(Native Method)
    	- waiting on <0x0000000799b032d8> (a java.lang.ref.ReferenceQueue$Lock)
    	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
    	- locked <0x0000000799b032d8> (a java.lang.ref.ReferenceQueue$Lock)
    	at sun.rmi.transport.DGCClient$EndpointEntry$RenewCleanThread.run(DGCClient.java:516)
    	at java.lang.Thread.run(Thread.java:662)
    
    注意以下几点
    1. wait on monitor entry:被阻塞的,肯定有问题
    2. runnable:注意IO线程
    3. in Object.wait():注意非线程池等待
    4. 虚拟机执行Full GC时,会阻塞所有的用户线程。因此,即时获取到同步锁的线程也有可能被阻塞。在查看线程Dump时,首先查看内存使用情况。

    Java中有两类线程:

    User Thread(用户线程)、Daemon Thread(守护线程)
    用户线程即运行在前台的线程,而守护线程是运行在后台的线程。 守护线程作用是为其他前台线程的运行提供便利服务,比如垃圾回收线程就是一个守护线程。当VM检测仅剩一个守护线程,而用户线程都已经退出运行时,VM就会退出,因为没有如果没有了被守护这,也就没有继续运行程序的必要了。如果有非守护线程仍然存活,VM就不会退出。守护线程并非只有虚拟机内部提供,用户在编写程序时也可以自己设置守护线程。用户可以用Thread的setDaemon(true)方法设置当前线程为守护线程。所有的用户线程退出了,虚拟机也就退出运行了。 因此,不要在守护线程中执行业务逻辑操作(比如对数据的读写等)。守护线程中产生的线程也是守护线程

    本文引自:https://www.cnblogs.com/myseries/p/12050083.html

    展开全文
  • 一、先说流程 1、找到CPU利用率持续比较高的进程, 命令: top ...2、找到CPU使用率较高的线程ID(TID): ...ps p 16480 -L -o pcpu,pid,tid,time,tname,cmd ...3、将获取的线程号(十进制数)...4、结合进程号和线程...

    一、先说流程

    1、找到CPU利用率持续比较高的进程, 命令:

    top

     

    2、找到CPU使用率较高的线程ID(TID):

    ps p 16480 -L -o pcpu,pid,tid,time,tname,cmd

    此处为:16498

     

    3、将获取的线程号(十进制数)转换成十六进制

    printf "%x\n" 16498

    结果:4072

     

    4、结合进程号和线程号,利用jstack查到异常代码所在行

    jstack -l <pid> | grep <thread-hex-id> -A 10 命令

    显示出错的堆栈信息,如下图:

    jstack -l 16480| grep 0x4072 -A 10

     -A 10 参数用来指定显示行数,否则只会显示一行信息。

    可以看到在代码的第13行有问题。也就是说是这一句导致cpu占用过高,在优化时,就可以针对这一部分代码进行优化。

    参考原文

     

     

    二、相关知识点

    JVM故障分析及性能优化系列文章

    JVM故障分析及性能优化系列之一:使用jstack定位线程堆栈信息

    JVM故障分析及性能优化系列之二:jstack生成的Thread Dump日志结构解析

    JVM故障分析及性能优化系列之三:jstat命令的使用及VM Thread分析

    JVM故障分析及性能优化系列之四:jstack生成的Thread Dump日志线程状态

    JVM故障分析及性能优化系列之五:常见的Thread Dump日志案例分析

    JVM故障分析及性能优化系列之六:JVM Heap Dump(堆转储文件)的生成和MAT的使用

    JVM故障分析及性能优化系列之七:使用MAT的Histogram和Dominator Tree定位溢出源

     

    还有一篇

    JVM调优之jstack找出最耗cpu的线程并定位代码

     

    展开全文
  • jvm线程堆栈信息收集

    2019-09-27 23:53:21
    查看整个JVM内存状态 jmap -heap [pid]要注意的是在使用CMS GC 情况下,jmap -heap的执行有可能会导致JAVA 进程挂起 查看JVM堆中对象详细占用情况jmap -histo [pid] 导出整个JVM 中内存信息jmap -dump:format=b,...

    1:
    其中jmap是java自带的工具

    查看整个JVM内存状态
    jmap -heap [pid]
    要注意的是在使用CMS GC 情况下,jmap -heap的执行有可能会导致JAVA 进程挂起

    查看JVM堆中对象详细占用情况
    jmap -histo [pid]

    导出整个JVM 中内存信息
    jmap -dump:format=b,file=文件名 [pid]
    jmap -dump:live,format=b,file=d:/20170417.dump PID

     

    jmap -dump:live,format=b,file=33.dump 20540

     

    2:

      kill -3 pid >> pid.txt

    或者

      jstack pid >> pid.txt

    3: 查看gc情况

    jstat -gcutil pid 1000 10

    转载于:https://www.cnblogs.com/litzhiai/p/9674479.html

    展开全文
  • windows下查看java进程 :jps ...昨天晚上总结了一下jstack(查看线程)、jmap(查看内存)和jstat(性能分析)命令。供大家参考  1.Jstack  1.1 jstack能得到运行java程序的java stack和native stac
  • 1、打印线程堆栈信息 jstack -l pid 2、线程堆栈信息输出到文件 jstack -l pid >> dumpFile 3、隔1秒打印一次GC信息, jstat -gcutil pid 1000
  • #!/bin/bash num=0 log="/tmp/jstack_thread_log/thread_info" cd /tmp if [ ! -d "jstack_thread_log" ]; then mkdir jstack_thread_log fi while ((num <= 10000)); do ID=`ps -ef | grep java | grep ...
  • 1. jstat 这个命令对于查看Jvm的堆栈信息很有用。能够查看eden,survivor,old,perm等heap的capacity,utility信息 对于查看系统是不是有能存泄漏以及参数设置是否合理有不错的意义 2. jstack 这个是用来查看jvm...
  • jstat命令

    2018-05-06 18:23:00
    Jstat 查看某个Java进程内的线程堆栈信息,用于监控基于HotSpot的JVM,对其堆的使用情况进行实时的命令行的统计,使用jstat我们可以对指定的JVM做如下监控: - 类的加载及卸载情况 - 查看新生代、老生代及持久代的...
  • jstat

    2019-06-15 14:32:25
    一、介绍 jstack是java虚拟机自带的一种堆栈跟踪工具。jstack用于打印出给定的java进程ID或corefile或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定... 针对活着的进程做本地的或远程的线程dump; ...
  • jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下: 1 jstack[option]pid 2 jstack[option]executablecore 3 jstack[option][server-id@]remote-...
  • Docker中查看JVM的信息: 1.列出docker容器:docker ps 2.标准输入和关联终端:docker exec -it 容器ID bash 3.查找出java进程: ps – ef | grep java 4.统计gc信息统计: ...示例1--jstack查看线程堆栈信息 ...
  • jvm监控Jstack和Jstat

    2021-09-12 18:34:04
    用于查看jvm线程堆栈的常用工具命令,可以获取每个线程内部的调用链以及每个线程当前的运行状态从而可以分析出死锁、循环、响应慢等性能问题。 jps命令查看java进程号,jstack命令: jstack 进程号,jstack能得到...
  • jstat:虚拟机统计信息监视工具(JVM Statistics Monitoring Tool) 说明:监视虚拟机的各种运行状态:类装载、内存、垃圾收集等运行数据。只用于Java进程或Java应用格式:jstat [option] PID [interval] [count]$ ...
  • linux查看java堆栈

    2020-10-28 15:02:54
    1、查看JAVA进程JVM参数 jinfo -flags pid(进程号) -XX:CICompilerCount=2 最大的并行编译数 -XX:InitialHeapSize=16777216 JVM 的初始堆内存大小 -XX:MaxHeapSize=257949696 JVM 的最大堆内存大小 -XX:MaxNewSize=...
  • JDK提供了Jstat等命令,用于监控JVM的运行...jstack:导出jvm的线程堆栈,导出后,可以用jvisual进行可视化分析,找出阻塞的线程; 本文主要介绍jstat命令,jstat命令可以根据指定的参数,打印出jvm内存使用统计信息
  • jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。以下详细介绍各个参数的意义。 jstat -class pid:显示加载class的数量,及所...
  • JVM调优总结 + jstat 分析

    千次阅读 2014-12-18 14:04:45
    原文地址:http://blog.163.com/bobile45@126/blog/static/9606199220139303343415/JVM调优总结 + jstat 分析 2013-10-30 15:34:34| 分类: 性能LR/Jmeter/Co|举报|字号 订阅jstat -gccause pid 1 每格1毫秒输出...
  • 查看线程堆栈命令:jstack命令 打印内存映射,制作堆Dump命令:Jmap 查看java 堆(heap)使用情况,执行命令: 查看堆内存(histogram)中的对象数量及大小。执行命令: 性能监控工具命令:jstat 参考资料 ...
  • 1、查看磁盘还剩多少空间,使用df命令 2、当前文件夹下的磁盘使用情况:(du --max-depth=1 -h后面没有显示跟路径,它默认是当前的路径。) 3、查看其中某一文件(文件夹)的大小:这里的大小是该文件夹下的大小的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,440
精华内容 2,976
关键字:

jstat查看线程堆栈