在常规的java开发当中,相信大家都有使用到jdk。在jdk包里面,官方提供了一套非常方便于我们java程序员进行疑难排查的工具包。这些工具主要是安装在了目录下的bin目录中。如下图所示:
表面上看起来,这些都不过是一些exe文件,但是实质上它们其实都是属于java程序,具体的实现都在lib目录底下的tools.jar里面。
JPS命令
这条命令有点类似于linux操作系统底下的ps命令,可以用于展示出相应的java应用程序。具体操作如下所示:
jps
会输出当前正在运行的java程序和相应的程序id号码
jps -q
会输出进程的id,但是不输出进类的名称
jps -l
可以查看java主函数的完整路径(包名+程序名)
现在我们对应用程序进行了以下的相关参数设置,分别是jvm参数和程序运行参数的设置
jps -v
可以查看java程序在运行的过程中,传递给jvm的参数信息
例如说程序初始化运行的时候,指定了相关的内存参数
jps -m
可以查看java程序在实际运行中所输入的程序参数信息:
jstat命令
jstat命令主要是一个用于观察java程序在运行过程中的实时信息,功能非常强大,通过它可以查看堆的详细信息内容。基本的使用用法如下所示:
jstat -class -pid
打印出指定id的java应用程序的类加载信息。
参数解释(从左往右):
Loaded:加载的class数目
Bytes:所占用的空间大小
Unloaded:卸载类的数目
Bytes:卸载类的空间大小
Time:加载和卸载类的花费时间
jstat -gc -pid
主要是查看指定java程序的GC相关信息
(单位统一是kB)
S0C: 年轻代第一个survivor space的内存大小
S1C: 年轻代第二个survivor space的内存大小
S0U: 年轻代第一个survivor space当前已使用的内存大小
S1U: 年轻代第二个survivor space当前已经使用的内存大小
EC: eden区的大小
EU: 是指eden区的使用大小
OC: 老年代的大小
OU: 老年代使用空间
PC: 永久代的大小
PU: 永久代使用空间
YGC: 新生代GC的次数
YGCT: 新生代GC的耗时
FGC: Full GC的次数
FGCT: Full GC的耗时
GCT: GC的总耗时
jstat -gccapacity -pid
比常规的jstat -gc id 所打印出来的信息更多,可以显示出每个年代的对象的最大值和最小值
(单位统一是kB)
NGCMN 新生代的最小值
NGCMX 新生代的最大值
NGC 当前新生代的大小
S0C: 年轻代第一个survivor space的内存大小
S1C: 年轻代第二个survivor space的内存大小
EC: eden区的大小
OGCMN老年代的最小值
OGCMX老年代的最大值
OC当前老年代的容量
OGC老年代的当前新生成的容量
OGCMX老年代的最大值
PGCMN永久代的最小值
PGCMX永久代的最大值
jstat -gccause -pid
查看最近一次gc的原因
jstat -gcutil -pid
命令也可以查看相关的gc回收信息
S0 年轻代中第一个survivor已使用的占当前容量百分比
S1 年轻代中第二个survivor已使用的占当前容量百分比
E 年轻代中Eden已使用的占当前容量百分比
O 老年代已使用的占当前容量百分比
YGC年轻代中gc次数
YGCT 年轻代中gc所用时间
FGC 老年代gc次数
FGCT 老年代gc所用时间
GCT 应用程序进行GC用的总时间
jinfo命令
jinfo -pid
该命令主要用于打印正在运行的java应用程序的扩展参数
jinfo -flag MaxHeapSize -pid
查看最大堆内存空间
jinfo -flag MaxTenuringThreshold 27534
查看新生代对象晋升到老年代对象的最大年龄
jinfo的主要作用是在程序运行过程中动态的进行相应jvm参数的修改,但是也并非是所有的jvm参数都允许修改,目前只支持以下几类参数动态修改:
$java -XX:+PrintFlagsFinal | grep manageable
intx CMSAbortablePrecleanWaitMillis = 100 {manageable}
intx CMSWaitDuration = 2000 {manageable}
bool HeapDumpAfterFullGC = false {manageable}
bool HeapDumpBeforeFullGC = false {manageable}
bool HeapDumpOnOutOfMemoryError = false {manageable}
ccstr HeapDumpPath = {manageable}
bool PrintClassHistogram = false {manageable}
bool PrintClassHistogramAfterFullGC = false {manageable}
bool PrintClassHistogramBeforeFullGC = false {manageable}
bool PrintConcurrentLocks = false {manageable}
bool PrintGC = false {manageable}
bool PrintGCDateStamps = false {manageable}
bool PrintGCDetails = false {manageable}
bool PrintGCTimeStamps = false {manageable}
例如动态设置和关闭HeapDumpBeforeFullGC
jmap命令
jmap -pid
该命令会打印出jvm虚拟机里面所加载的每个共享对象的地址,内存大小等信息
jmap -heap -pid
命令会打印出相应堆的详细各个属性的信息,包括了堆的分代大小,内存使用情况
jmap -histo:live pid
该命令可以用来打印堆里面的对象统计信息
这条命令打印出来之后会有相应的堆对象和堆对象的实例个数。
jstack 命令
该命令可以打印线程的堆栈信息,最主要的功能在于它对于锁的信息判断。该命令可以自动查找到相应的死锁信息:
例如以下的一个死锁案例代码:
public class DeadLock {
public String locka="a";
public String lockb="b";
public static void main(String[] args) {
new DeadLock().deadLock();
}
public void deadLock(){
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
synchronized (locka){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockb){
}
}
}
});
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
synchronized (lockb){
synchronized (locka){
System.out.println("this is b");
}
}
}
});
t1.start();
t2.start();
}
}
jstack -l pid命令
当程序运行之后通过jps命令发现死锁,使用jstack -l pid命令追踪程序
为了方便查看,通过命令重定向将异常导入到了txt里面进行查看:
通过对日志信息里面的关键字进行逐一排查便可找到死锁的详细位置。
小结
jps,jstat,jinfo,jmap,jstack这些常用的jdk命令在java程序员进行线上排查的时候经常会使用到,因此本文特定做了一次汇总,方便日后的回顾和查看。