您的位置:首页 > 其它

JVM常用工具

2015-10-29 23:32 316 查看
jps: 查找当前虚拟机进程

(1)jps -m 列出当前虚拟机进程以及传给虚拟机启动主进程main方法的参数

(2)jps -l 输出主类的名称

(3)jps -v 输出虚拟机启动参数

(4)jps -q 只输出虚拟机进程号

jinfo: 查看和调整JVM参数

(1)jinfo [option选项] [PID JVM进程]

(2)jinfo -flag [JVM参数名称] [PID]

比如 jinfo -flag NewSize 19508 会打印出来 -XX:NewSize 即新生代内存配置的参数

(3)jinfo -flag +[JVM参数名称] [PID] 使该项参数生效

(4)jinfo -flag -[JVM参数名称] [PID] 禁用该项参数

比如 jinfo -flag -NewSize 19508 禁用新生代内存配置项,当然这个配置项是不允许的,会报错:

Exception in thread “main” com.sun.tools.attach.AttachOperationFailedException: flag ‘NewSize’ cannot be changed

(5)jinfo -flag [JVM参数名称]=[参数的值]

比如 jinfo -flag NewSize=5570560 注意单位是Byte,不是M,当然这个配置项也是不允许设置的~~~

jstat监视JVM运行状态,比如类装载、GC等数据

先通过jsp或者ps aux|grep java 命令获得jvm进程号,比如是 19508

(1)jstat -gcutil 19508 输出当前JVM的GC情况

S0S1EOPYGCYGCTFGCFGCTGCT
58.370.0093.196.6958.21461.01072.0553.065
(2)jstat -gc 19508 1000 5 每隔1000毫秒即每隔1秒,总共收集5次GC情况

S0CS1CS0US1UECEUOCOUPCPUYGCYGCTFGCFGCTGCT
10432.010048.06089.30.0307200.0182057.6720896.048229.8144448.084077.9461.01072.0553.065
10432.010048.06089.30.0307200.0182314.8720896.048229.8144448.084077.9461.01072.0553.065
10432.010048.06089.30.0307200.0182330.7720896.048229.8144448.084077.9461.01072.0553.065
10432.010048.06089.30.0307200.0182682.4720896.048229.8144448.084077.9461.01072.0553.065
10432.010048.06089.30.0307200.0182692.1720896.048229.8144448.084077.9461.01072.0553.065
(3)S 代表Survivor区,E代表Eden区,P代表Permanent区,O代表Old区,如下

S0C:年轻代中第一个survivor(幸存区)的容量 (字节)

S1C:年轻代中第二个survivor(幸存区)的容量 (字节)

S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节)

S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)

EC:年轻代中Eden(伊甸园)的容量 (字节)

EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)

OC:Old代的容量 (字节)

OU:Old代目前已使用空间 (字节)

PC:Perm(持久代)的容量 (字节)

PU:Perm(持久代)目前已使用空间 (字节)

YGC:从应用程序启动到采样时年轻代中gc次数

YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)

FGC:从应用程序启动到采样时old代(全gc)gc次数

FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)

GCT:从应用程序启动到采样时gc用的总时间(s)

NGCMN:年轻代(young)中初始化(最小)的大小 (字节)

NGCMX:年轻代(young)的最大容量 (字节)

NGC:年轻代(young)中当前的容量 (字节)

OGCMN:old代中初始化(最小)的大小 (字节)

OGCMX:old代的最大容量 (字节)

OGC:old代当前新生成的容量 (字节)

PGCMN:perm代中初始化(最小)的大小 (字节)

PGCMX:perm代的最大容量 (字节)

PGC:perm代当前新生成的容量 (字节)

S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比

S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比

E:年轻代中Eden(伊甸园)已使用的占当前容量百分比

O:old代已使用的占当前容量百分比

P:perm代已使用的占当前容量百分比

S0CMX:年轻代中第一个survivor(幸存区)的最大容量 (字节)

S1CMX :年轻代中第二个survivor(幸存区)的最大容量 (字节)

ECMX:年轻代中Eden(伊甸园)的最大容量 (字节)

DSS:当前需要survivor(幸存区)的容量 (字节)(Eden区已满)

TT: 持有次数限制

MTT : 最大持有次数限制

jstack监视JVM线程堆栈情况,排查问题首选工具

jstack [option] PID

可用选项包括:

jstack -l PID 除了堆栈,显示关于锁的附加信息

jstack -m PID 开启mixd mode 即混合模式,还会打印C/C++堆栈

jstack -F PID 如果jstack正常请求没有想学习,强制输出线程堆栈

(1)比如JVM进程号是 4834,那么 jstack 4834 会打印出整个JVM堆栈

(2)如果想要保存堆栈信息,可以输出到一个文件,比如 jstack 4834 > javacore.txt

请仔细看看堆栈内容

模拟一个线上故障,使用jstack来定位问题

(1)写一段简单代码,启动Java应用程序,模拟问题

import java.util.List;
import java.util.ArrayList;
public class Test {
public static void main(String[] args){
List<User> list = new ArrayList<User>();
// 不停的构造新的对象,且main方法运行后,该线程就一直不会停止
// 对于整个JVM应用程序来说,由于就模拟了这一个线程,因此肯定是最耗时的线程
while(true){
User u = new User();
list.add(u);
try{
System.out.println("size:" + list.size());
Thread.sleep(200);
}catch(Exception e){
}
}
}
public static class User {
private byte[] bytes = new byte[1024];
}
}


(2)查找JVM进程号

第一种方式:jps 直接找到进程号,比如是 4834

第二种方式:ps -ef | grep java ,也能找到JVM进程号,比如 4834

(3)定位当前JVM中最耗时、最耗CPU、最耗内存的Java线程

这里要结合top命令来使用:

top -Hp PID 本例中,即 top -Hp 4834 则会进入top控制台,并且追踪的是当前JVM

在这个控制台,可以根据 T(时间)、P(CPU)、M(内存) 来排序

比如本例中,就是要找最耗时的Java线程,那么在top控制台,直接输入大写字母 T ,即根据时间来排序

得到最耗时的Java线程号,比如是 4835

如果你直接使用 jstack 命令查看过Java堆栈信息,会发现每一个线程都是用十六进制标识的

因此,使用 printf “%x\n” 4835 将当前线程号转成十六进制,得到 12e3

最后:jstack PID | grep 线程号 本例中即 jstack 4834 | grep 12e3

在JDK6以上,比如JDK8环境,那么打印出来的是:

"main" #1 prio=5 os_prio=0 tid=0xb6907000 nid=0x12e3 waiting on condition [0xb6aa1000]


在JDK6环境,打印出来的,则直接定位到 Test.java 的main方法

"Thread-Test" prio=5 os_prio=0 tid=0xb6907000 nid=0x12e3 waiting on condition [0xb6aa1000]


jstat监视JVM运行状态,比如类装载、GC等数据
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jvm jvm工具