java虚拟机自带的工具,将jdk的lib下的tools包解压后可以发现工具的源码,或者直接在bin目录下也能看到工具.exe执行文件
1. jps
这个命令和ps -ef |grep java有相似的用处
jps是典型的jvm工具,查看jvm当前运行的项目的进程pid
实践:
运行一个springboot项目
jps -v 展示当前的jvm环境
jps -l 展示当前运行的项目进程pid
2. jstat -gc 6278 250 20 (进程id/250毫秒打印间隔/打印次数20) 打印gc信息
3.jinfo
实时查看和调整虚拟机的各项参数,虽然使用jps -v 可以查看虚拟机启动时显示指定的参数列表,但是如果想知道
未被显式指定的参数的系统默认值,除了去找资料,就只能使用jinfo的-flag选项进行查询了
jinfo 6278(进程pid)展示所有信息
4.jmap
jmap用于生成堆转储快照,如果不使用jmap命令,想要获取java堆转储快照,还有一些暴力的手段:
-XX:+HeapDumpOnOutMemoryError参数,可以让虚拟机在发生OOM的时候自动生成dump文件,便于系统复盘
实战:
①使用jps列出系统内的项目
jps
②查看项目的堆信息
jmap -heap 6872
jmap -histo 6872|more more用来分页显示
jmap -dump:format=b,file=./a.bin 6872 手动拷贝堆快照到本地,便于后边对转储的快照进行分析
5.jhat
jvm heap analysis tools jvm内存分析工具,一般搭配jmap -dump来使用,因为jhat分析十分耗内存,先将堆快照转储到本地,节省服务器资源
实战:
①模拟OOM代码:
/**
* @Auther: jorian
* @Date: 2019/8/11 23:17
* @Description:
*/
public class OOMError {
public static void main(String []args){
String name = "xdclass";
for(int i =0;i<1000000000;i++){
name+=name;
}
System.out.println(name);
}
}
②配置启动参数,在发生oom异常时自动保存堆快照
-Xms20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:\Users\Administrator\Desktop
③启动程序,因为必然发生oom异常,我们可以发现桌面多出来一个快照文件。
④分析快照
jhat 快照文件名 会启动一个server端,port:7000
可以直接在浏览器打开,一般我们拉到最后分析最后的两条
说明:jhat命令已经非常老旧,后面我们会介绍更多的图形界面的内存文件分析工具
6.jstack
当线程出现长时间停顿,我们可以使用jstack生成线程的快照
线程快照就是当前虚拟机内每条线程正在执行的方法堆栈的集合
线上程序一般不能使用kill进程pid的方式直接关闭,shutdownHook
jstatck 14665(进程pid) 查看栈快照
7.死锁模拟及使用jstack观察死锁
@SpringBootApplication
public class Jvm01Application {
public static void main(String[] args) {
SpringApplication.run(Jvm01Application.class, args);
}
/**
* postconstruct在springboot项目启动的时候执行的方法
* 在bean加载完但用户线程进来之前执行的方法
*/
private static Object Lock1 = new Object();
private static Object Lock2 = new Object();
@PostConstruct
public void deadLock(){
new Thread(()->{
synchronized (Lock1){
try {
System.out.println(Thread.currentThread().getName()+"得到lock1");
Thread.sleep(3000L);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (Lock2){
System.out.println(Thread.currentThread().getName()+"得到lock2");
}
}
},"线程1").start();
new Thread(()->{
synchronized (Lock2){
try {
System.out.println(Thread.currentThread().getName()+"得到lock2");
Thread.sleep(3000L);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (Lock1){
System.out.println(Thread.currentThread().getName()+"得到lock1");
}
}
},"线程2").start();
}
}
①启动项目后,使用jps获得项目的进程pid
②使用jstack -l pid
可以看到线程死锁的提示: