一、jps 虚拟机进程状况
jps(JVM Process Status Tool),它的功能与ps命令类似,可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID(Local Virtual Machine Identifier,LVMID),类似于 ps -ef | grep java 的功能。
「命令格式」
jps [ options ] [ hostid ]
-
options:选项、参数,不同的参数可以输出需要的信息
-
hostid:远程查看
「选项列表」
1.1 jps -q,只列出进程ID
1.2 jps -l,输出当前运行类全称
1.3 jps -m,列出传给main()函数的参数
1.4 jps -v,输出虚拟机进程启动时JVM参数
1.5 jps -lVvm,完整参数
二、jcmd 虚拟机诊断命令
jcmd,是从jdk1.7开始新发布的 JVM 相关信息诊断工具,可以用它来导出堆和线程信息、查看Java进程、执行GC、还可以进行采样分析(jmc 工具的飞行记录器)。注意其使用条件是只能在被诊断的JVM同台sever上,并且具有相同的用户和组(user and group).
「命令格式」
jcmd <pid | main class> <command ...|PerfCounter.print|-f file>
-
pid,接收诊断命令请求的进程ID
-
main class,接收诊断命令请求的进程main类。
-
-
command,接收诊断命令请求的进程main类。
-
PerfCounter.print,打印目标 Java 进程上可用的性能计数器。
-
-f file,从文件file中读取命令,然后在目标Java进程上调用这些命令。
-
-l,查看所有进程列表信息。
-
-h、-help,查看帮助信息。
2.1 jcmd pid VM.flags,查看JVM启动参数
2.2 jcmd pid VM.uptime,查看JVM运行时长
2.3 jcmd pid PerfCounter.print,查看JVM性能相关参数
2.4 jcmd pid GC.class_histogram,查看系统中类的统计信息
2.5 jcmd pid Thread.print,查看线程堆栈信息
2.6 jcmd pid VM.system_properties,查看JVM系统参数
自定义key值
2.7 jcmd pid GC.heap_dump 路径,导出heap dump文件
2.8 jcmd pid help,列出可执行操作
三、 jinfo Java配置信息工具
jinfo(Configuration Info for Java),实时查看和调整JVM的各项参数。
在上面讲到 jps -v
指令时,可以看到它把虚拟机启动时显式的参数列表都打印出来了,但如果想更加清晰的看具体的一个参数或者想知道未被显式指定的参数时,就可以通过 jinfo -flag 来查询了。
「命令格式」
jinfo [ option ] pid
「使用方式」
各种JVM参数你都可以去查询,这样更加方便的只把你要的显示出来。
四、jstat 收集虚拟机运行数据
jstat(JVM Statistics Monitoring Tool),用于监视虚拟机各种运行状态信息。它可以查看本地或者远程虚拟机进程中,类加载、内存、垃圾收集、即时编译等运行时数据。
「命令格式」
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
-
vmid:如果是查看远程机器,需要按照此格式:
[protocol:][//]lvmid[@hostname[:port]/servername]
-
interval和count,表示查询间隔和次数,比如每隔1000毫秒查询一次进程ID的gc收集情况,每次查询5次。
jstat -gc 111552 1000 5
4.01 jstat -class,类加载统计
Loaded,加载class的数量
Bytes:所占用空间大小
Unloaded:未加载数量
Bytes:未加载占用空间
Time:时间
4.02 jstat -compiler,编译统计
Compiled:编译数量
Failed:失败数量
Invalid:不可用数量
Time:时间
FailedType:失败类型
FailedMethod:失败方法
4.03 jstat -gc,垃圾回收统计
S0C、S1C,第一个和第二个幸存区大小
S0U、S1U,第一个和第二个幸存区使用大小
EC、EU,伊甸园的大小和使用
OC、OU,老年代的大小和使用
MC、MU,方法区的大小和使用
CCSC、CCSU,压缩类空间大小和使用
YGC、YGCT,年轻代垃圾回收次数和耗时
FGC、FGCT,老年代垃圾回收次数和耗时
GCT,垃圾回收总耗时
4.04 jstat -gccapacity,堆内存统计
NGCMN、NGCMX,新生代最小和最大容量
NGC,当前新生代容量
S0CMX,最大幸存0区大小
S0C,当前幸存0区大小
S1CMX,最大幸存1区大小
S1C,当前幸存1区大小
ECMX,最大伊甸园区大小
EC,当前伊甸园区大小
YGC,年轻代垃圾回收次数
FGC,老年代回收次数
4.06 jstat -gcnew,新生代垃圾回收统计
4.07 jstat -gcoldcapacity,老年代内存统计
4.08 jstat -gcutil,垃圾回收统计
4.09 jstat -printcompilation,JVM编译方法统计
五、 jmap 内存映射工具
jmap(Memory Map for Java),用于生成堆转储快照(heapdump文件)。
jmap 的作用除了获取堆转储快照,还可以查询finalize执行队列、Java 堆和方法区的详细信息。
「命令格式」
jmap [ option ] pid
-
option:选项参数
-
pid:需要打印配置信息的进程ID
-
executable:产生核心dump的Java可执行文件
-
core:需要打印配置信息的核心文件
-
server-id:可选的唯一id,如果相同的远程主机上运行了多台调试服务器,用此选项参数标识服务器
-
remote server IP or hostname:远程调试服务器的IP地址或主机名
5.1 jmap -heap,堆详细信息
5.2 jmap -clstats,打印加载类
5.3 jmap -dump,堆转储文件
六、 jstack Java堆栈跟踪工具
jstack(Stack Trace for Java),用于生成虚拟机当前时刻的线程快照(threaddump、javacore)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如:线程死锁、死循环、请求外部资源耗时较长导致挂起等。线程出现听顿时通过jstack来查看各个线程的调用堆栈,就可以获得没有响应的线程在搞什么鬼。
「命令格式」
jstack [ option ] vmid
生产环境大型项目,一般都对接APM工具,可视化分析GC情况比较方便。
七、主线程异常崩溃,JVM是否崩溃退出?
1、测试程序如下
import java.util.concurrent.TimeUnit;
/**
* 测试主线程崩溃,会不会导致JVM崩溃退出
*/
public class TestJvmExit {
public static void main(String[] args) {
NewThread thread = new NewThread();
thread.setName("NewThread");
thread.start();
// 验证空指针异常
Integer num=null;
if(num.equals(5)){
System.out.println("Tail");
}
}
}
class NewThread extends Thread{
@Override
public void run() {
while (true){
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("NewThread Run");
}
}
}
什么时候JVM会退出?Thread类上面的内容
也就是说只有在 JVM 的所有线程都是守护线程(daemon thread)的时候才会完全退出,什么是守护线程?守护线程其实是为其他线程服务的线程,比如垃圾回收线程就是典型的守护线程,既然是为其他线程服务的,那么一旦其他线程都不存在了,守护线程也没有存在的意义了,于是 JVM 也就退出了,守护线程通常是 JVM 运行时帮我们创建好的,当然我们也可以自己设置,
验证如下:
thread.setDaemon(true);
一定是要在线程启动前设置为守护线程,否则不生效.
主线程崩溃后,所有子线程为守护线程时候,JVM退出.
结论:
1、当主线程崩溃后不是VirtualMachineError的异常时候,JVM任务触发了自我保护机制,直接退出,例如非法访问内存。
2、当不是致命错误时候,如果此时还有线程不是守护线程时候会继续运行,如果所有线程都是守护线程时候了,那么也就没必要继续工作了,直接退出。
垃圾回收线程就是典型的守护线程。