用法介绍
jps命令:显示全部进程号和短的类名称
Jps –q 命令:只显示进程号
Jps –l 用于传输主函数的完整路径
Jps –v 显示传递给Java虚拟机的参数(感受这个命令才是完美,把虚拟机的一些参数全都打印出来) html
Jstack命令主要用来查看Java线程的调用堆栈的,能够用来分析线程问题(如死锁)。谈到线程,在Java里面,线程一共有6中状态java
Monitor
在多线程的 JAVA程序中,实现线程之间的同步,就要说说 Monitor。 Monitor是 Java中用以实现线程之间的互斥与协做的主要手段,它能够当作是对象或者 Class的锁。每个对象都有,也仅有一个 monitor。下 面这个图,描述了线程和 Monitor之间关系,以 及线程的状态转换图: c++
进入区(Entrt Set):算法
表示线程经过synchronized要求获取对象的锁。若是对象未被锁住,则迚入拥有者;不然则在进入区等待。一旦对象锁被其余线程释放,当即参与竞争。服务器
拥有者(The Owner):markdown
表示某一线程成功竞争到对象锁。网络
等待区(Wait Set):多线程
表示线程经过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。oracle
从图中能够看出,一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在 “Wait Set”中等待的线程状态是 “in Object.wait()”。 先看 “Entry Set”里面的线程。咱们称被 synchronized保护起来的代码段为临界区。当一个线程申请进入临界区时,它就进入了 “Entry Set”队列。对应的 code就像:框架
synchronized(obj) {
......... }
调用修饰
表示线程在方法调用时,额外的重要的操做。线程Dump分析的重要信息。修饰上方的方法调用。
locked <地址> 目标:使用synchronized申请对象锁成功,监视器的拥有者。
waiting to lock <地址> 目标:使用synchronized申请对象锁未成功,在迚入区等待。
waiting on <地址> 目标:使用synchronized申请对象锁成功后,释放锁幵在等待区等待。
parking to wait for <地址> 目标
locked
at oracle.jdbc.driver.PhysicalConnection.prepareStatement - locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection) at oracle.jdbc.driver.PhysicalConnection.prepareStatement - locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection) at com.jiuqi.dna.core.internal.db.datasource.PooledConnection.prepareStatement
经过synchronized关键字,成功获取到了对象的锁,成为监视器的拥有者,在临界区内操做。对象锁是能够线程重入的。
waiting to lock
at com.jiuqi.dna.core.impl.CacheHolder.isVisibleIn(CacheHolder.java:165) - waiting to lock <0x0000000097ba9aa8> (a CacheHolder) at com.jiuqi.dna.core.impl.CacheGroup$Index.findHolder at com.jiuqi.dna.core.impl.ContextImpl.find at com.jiuqi.dna.bap.basedata.common.util.BaseDataCenter.findInfo
经过synchronized关键字,没有获取到了对象的锁,线程在监视器的进入区等待。在调用栈顶出现,线程状态为Blocked。
waiting on
at java.lang.Object.wait(Native Method) - waiting on <0x00000000da2defb0> (a WorkingThread) at com.jiuqi.dna.core.impl.WorkingManager.getWorkToDo - locked <0x00000000da2defb0> (a WorkingThread) at com.jiuqi.dna.core.impl.WorkingThread.run
经过synchronized关键字,成功获取到了对象的锁后,调用了wait方法,进入对象的等待区等待。在调用栈顶出现,线程状态为WAITING或TIMED_WATING。
parking to wait for
park是基本的线程阻塞原语,不经过监视器在对象上阻塞。随concurrent包会出现的新的机制,不synchronized体系不一样。
线程动做
线程状态产生的缘由
runnable:状态通常为RUNNABLE。
in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。
waiting for monitor entry:进入区等待,状态为BLOCKED。
waiting on condition:等待区等待、被park。
sleeping:休眠的线程,调用了Thread.sleep()。
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)
jstack 命令详解
简单介绍:
F当’jstack [-l] pid’没有相应的时候强制打印栈信息 -l长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表. -m打印java和native c/c++框架的全部栈信息. -h | -help打印帮助信息 pid 须要被打印配置信息的java进程id,能够用jps查询.
第一个实战代码:
/** * Created by Cser_W on 2018/7/10. */ public class JstackDemo { public static void main(String[] args){ while (true) { //do nothing } } }
先利用 jps 查看进程号
利用jstack 进程号查看线程堆栈信息,若是发现本身写的代码一直处于Runnable状态,这有很大多是本身写了个死循环。
第二个实战代码
/** * Created by Cser_W on 2018/7/10. */ public class JstackDemo1 { public static void main(String[] args){ Thread thread = new Thread(new Thread1()); thread.start(); } } class Thread1 extends Thread { @Override public void run(){ while (true) { System.out.println(1); } } }
咱们能看到:
线程的状态: WAITING 线程的调用栈 线程的当前锁住的资源: < < <0x00000000da380ee0>>> 线程当前等待的资源:< < <0x00000000da380ee0>>>
为何同时锁住的等待同一个资源:
线程的执行中,先得到了这个对象的 Monitor(对应于 locked < <0x00000000da380ee0>>)。当执行到 obj.wait(), 线程即放弃了 Monitor的全部权,进入 “wait set”队列(对应于 waiting on < <0x00000000da380ee0>> )。
死锁模拟实战
package com.wxy.test; /** * Created by Cser_W on 2018/7/10. */ public class JstackDemo2 { public static void main(String[] args){ Thread thread1 = new Thread(new DeadLockClass(true)); Thread thread2 = new Thread((new DeadLockClass(false))); thread1.start(); thread2.start(); } } class DeadLockClass implements Runnable { public boolean flag; DeadLockClass(boolean flag) { this.flag = flag; } @Override public void run() { if (flag) { while (true) { synchronized (Suo.o1) { System.out.println("o1" + Thread.currentThread().getName()); synchronized (Suo.o2) { System.out.println("o2" + Thread.currentThread().getName()); } } } } else { while (true) { synchronized (Suo.o2) { System.out.println("o2" + Thread.currentThread().getName()); synchronized (Suo.o1) { System.out.println("o1" + Thread.currentThread().getName()); } } } } } } class Suo { static Object o1 = new Object(); static Object o2 = new Object(); }
运行输出:
上图已经锁死,只要两个线程都启动起来,一定会发生死锁。这个时候赶忙拿jstack练手了
用jstack命令显示:
堆map的概述
堆Dump是反应Java堆使用状况的内存镜像,其中主要包括系统信息、虚拟机属性、完整的线程Dump、全部类和对象的状态等。 通常,在内存不足、GC异常等状况下,咱们就会怀疑有内存泄露。这个时候咱们就能够制做堆Dump来查看具体状况
用法摘要
Usage:
jmap [option] <pid>
(to connect to running process) jmap [option] <executable <core> (to connect to a core file) jmap [option] [server_id@]<remote server IP or hostname> (to connect to remote debug server) where <option> is one of: <none> to print same info as Solaris pmap -heap to print java heap summary -histo[:live] to print histogram of java object heap; if the "live" suboption is specified, only count live objects -permstat to print permanent generation statistics -finalizerinfo to print information on objects awaiting finalization -dump:<dump-options> to dump java heap in hprof binary format dump-options: live dump only live objects; if not specified, all objects in the heap are dumped. format=b binary format file=<file> dump heap to <file> Example: jmap -dump:live,format=b,file=heap.bin <pid> -F force. Use with -dump:<dump-options> <pid> or -histo to force a heap dump or histogram when <pid> does not respond. The "live" suboption is not supported in this mode. -h | -help to print this help message -J<flag> to pass <flag> directly to the runtime system
指定进程号(pid)的进程 jmap [ option ] 指定核心文件 jmap [ option ] 指定远程调试服务器jmap [ option ] [server-id@]
参数:
option 选项参数是互斥的(不可同时使用)。想要使用选项参数,直接跟在命令名称后便可。
pid 须要打印配置信息的进程ID。该进程必须是一个Java进程。想要获取运行的Java进程列表,你可使用jps。
executable 产生核心dump的Java可执行文件。
core 须要打印配置信息的核心文件。
remote-hostname-or-IP 远程调试服务器的(请查看jsadebugd)主机名或IP地址。
server-id 可选的惟一id,若是相同的远程主机上运行了多台调试服务器,用此选项参数标识服务器。
选项:
若是使用不带选项参数的jmap打印共享对象映射,将会打印目标虚拟机中加载的每一个共享对象的起始地址、映射大小以及共享对象文件的路径全称。这与Solaris的pmap工具比较类似。
-dump:[live,]format=b,file= 以hprof二进制格式转储Java堆到指定filename的文件中。live子选项是可选的。若是指定了live子选项,堆中只有活动的对象会被转储。想要浏览heap dump,你可使用jhat(Java堆分析工具)读取生成的文件。
-finalizerinfo 打印等待终结的对象信息。
-heap 打印一个堆的摘要信息,包括使用的GC算法、堆配置信息和generation wise heap usage。
-histo[:live] 打印堆的柱状图。其中包括每一个Java类、对象数量、内存大小(单位:字节)、彻底限定的类名。打印的虚拟机内部的类名称将会带有一个’*’前缀。若是指定了live子选项,则只计算活动的对象。
-permstat 打印Java堆内存的永久保存区域的类加载器的智能统计信息。对于每一个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会被打印。此外,包含的字符串数量和大小也会被打印。
-F 强制模式。若是指定的pid没有响应,请使用jmap -dump或jmap -histo选项。此模式下,不支持live子选项。
-h 打印帮助信息。
-help 打印帮助信息。
-J 指定传递给运行jmap的JVM的参数。
Jmap –heap pid
Jmap –histo pid
总结:
1. 若是程序内存不足或者频繁GC,颇有可能存在内存泄露状况,这时候就要借助Java堆Dump查看对象的状况。
2.要制做堆Dump能够直接使用jvm自带的jmap命令
3.能够先使用jmap -heap命令查看堆的使用状况,看一下各个堆空间的占用状况。
4.使用jmap -histo:[live]查看堆内存中的对象的状况。若是有大量对象在持续被引用,并无被释放掉,那就产生了内存泄露,就要结合代码,把不用的对象释放掉。
5.也可使用 jmap -dump:format=b,file=命令将堆信息保存到一个文件中,再借助jhat命令查看详细内容
6.在内存出现泄露、溢出或者其它前提条件下,建议多dump几回内存,把内存文件进行编号归档,便于后续内存整理分析。
用法讲解
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
参数解释:
Option — 选项,咱们通常使用 -gcutil 查看gc状况
vmid — VM的进程号,即当前运行的java进程号
interval– 间隔时间,单位为秒或者毫秒
count — 打印次数,若是缺省则打印无数次
参数 interval 和 count 表明查询间隔和次数,若是省略这两个参数,说明只查询一次。
示例:
Jstat –gc 4100 250 5
上图中参数的意思:
S0C 年轻代中第一个survivor(幸存区)的容量 (字节)
S0U 年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
EC 年轻代中Eden(伊甸园)的容量 (字节)
EU 年轻代中Eden(伊甸园)目前已使用空间 (字节)
OU Old代目前已使用空间 (字节)
PC Perm(持久代)的容量 (字节)
PU Perm(持久代)目前已使用空间 (字节)
YGC 从应用程序启动到采样时年轻代中gc次数
FGC 从应用程序启动到采样时old代(全gc)gc次数
FGCT 从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT 从应用程序启动到采样时gc用的总时间(s)
Jstat –class 4100 250 5 显示加载class的数量,及所占空间等信息。
Loaded 装载的类的数量
Unloaded 卸载类的数量
Bytes 卸载类的字节数
Time 装载和卸载类所花费的时间
jstat -compiler 显示VM实时编译的数量等信息
Compiled 编译任务执行数量
Invalid 编译任务执行失效数量
Time 编译任务消耗时间
FailedType 最后一个编译失败任务的类型
FailedMethod 最后一个编译失败任务所在的类及方法
Jstat –gccapacity 4100
NGCMN 年轻代(young)中初始化(最小)的大小(字节)
NGC 年轻代(young)中当前的容量 (字节)
S0C 年轻代中第一个survivor(幸存区)的容量 (字节)
S1C 年轻代中第二个survivor(幸存区)的容量 (字节)
EC 年轻代中Eden(伊甸园)的容量 (字节)
OGCMN old代中初始化(最小)的大小 (字节)
OGCMX old代的最大容量(字节)
OGC old代当前新生成的容量 (字节)
OC Old代的容量 (字节)
PGCMN perm代中初始化(最小)的大小 (字节)
PGCMX perm代的最大容量 (字节)
PGC perm代当前新生成的容量 (字节)
PC Perm(持久代)的容量 (字节)
YGC 从应用程序启动到采样时年轻代中gc次数
FGC 从应用程序启动到采样时old代(全gc)gc次数
【Java命令学习系列(二)-Jstack】http://www.hollischuang.com/archives/110
【Java命令学习系列(三)—Jmap】http://www.hollischuang.com/archives/303
【Java命令学习系列(四)—jstat】http://www.hollischuang.com/archives/481