Java中高级工程师必备线上虚拟机(JVM)工具
文章目录
虚拟机工具的意义
-
给⼀个系统定位问题的时候,知识、经验是关键基础,数据是依据,⼯具是运⽤知识处理数据的⼿段
-
数据包括:运⾏⽇志、异常堆栈、GC ⽇志、线程快照( threaddump/javacore⽂件)、堆转储快照( heapdump/hprof⽂件)等。使⽤适当的虚拟机监控和分析的⼯具可以加快我们分析数据、定位解决问题的速度
-我们所使用的工具在以下路径可以查看
红框标注为我们主要用到的几个命令,也就是我们说的工具,对应可执行文件,这些可执行文件的源码与字节码文件(.class)放在lib/tool.jar下,这也体现了我们所说的 Java特性:一次编译处处运行
JPS
JPS(JVM Process Status Tool)是其中的典型jvm⼯具。除了名字像 UNIX 的 ps 命令之外,它的功能也和 ps 命令类似:可以列出正在运⾏的虚拟机进程,并显示虚拟机执⾏主类(Main Class, main()函数所在的类名称以及这些进程的本地虚拟机唯- ID (Local VirtualMachine Identififier, LVMID),虽然功能⽐较单⼀,但它是使⽤频率最⾼的 JDK 命令⾏⼯具
实战
在java环境变量配置没问题的情况下,直接的cmd里敲jps即可查看当前java进程
格式 jps [options]
options有以下常用
- -l:输出完全的包名,应用主类名,jar的完全路径名;
- -v:输出jvm参数 ;
Jstat
Jstat (JVM Statistics Monitoring Tool)是⽤于监视虚拟机各种运⾏状态信息的命令⾏⼯具。
它可以显示本地或者远程-虚拟机进程中的类装载、内存、垃圾收集、JIT 编译等运⾏数据,在没有 GU 图形界⾯,只提供了纯⽂本控制台环境的服务器上,它将是运⾏期定位虚拟机性能问题的⾸选⼯具
实战
jstat -gc 21700 250 20
-gc表示打印垃圾收集器相关信息,21700表示进程id ,可由jps指令获得,250表示250毫秒打印⼀次 ,20表示⼀共打印20次
S0C:第⼀个幸存区的⼤⼩
S1C:第⼆个幸存区的⼤⼩
S0U:第⼀个幸存区的使⽤⼤⼩
S1U:第⼆个幸存区的使⽤⼤⼩
EC:伊甸园区的⼤⼩
EU:伊甸园区的使⽤⼤⼩
OC:⽼年代⼤⼩
OU:⽼年代使⽤⼤⼩
MC:⽅法区⼤⼩
MU:⽅法区使⽤⼤⼩
CCSC:压缩类空间⼤⼩
CCSU:压缩类空间使⽤⼤⼩
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:⽼年代垃圾回收次数
FGCT:⽼年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
Jinfo
jinfo (Confifiguration Info for Java)的作⽤是实时地查看和调整虚拟机各项参数。使⽤ jps 命令的-v 参数可以查看虚拟机启动时显式指定的参数列表,但如果想知道未被显式指定的参数的系统默认值,除了去找资料外,就只能使⽤ info 的-flflag 选项进⾏查询了
实战
jinfo 21700(进程号)
可展示项目所有信息
Jmap
-
Jmap (Memory Map for Java)命令⽤于⽣成堆转储快照。如果不使⽤ jmap 命令,要想获取 Java 堆转储快照,还有⼀些⽐较“暴⼒”的⼿段:
-
-XX: +HeapDumpOnOutOfMemoryError
参数,可以让虚拟机在 OOM 异常出现之后⾃动⽣成 dump ⽂件,⽤于系统复盘环节 -
和 info 命令⼀样,jmap 有不少功能在 Windows 平台下都是受限的,除了⽣成 dump ⽂件的- dump 选项和⽤于查看每个类的实例、空间占⽤统计的histo选项在所有操作系统都提供之外,其余选项都只能在Linux/Solaris 下使⽤
实战
-dump
–生成 Java 堆转储快照。格式为:-dump: format=b, fifile=
如
windows: jmap -dump:format=b,file=d:\a.bin 1234
-
一般设置在发生OOM异常的时候,自动dump快照
-
一般与Jhat一起使用
–显示堆中对象统计信息,包括类、实例数量、合计容量
jmap -histo 21700 |more
more表示使用分页查看
C : char
B :byte
I :Int
这三类在堆中占有一般排前三,如果其他类容量超过它们,考虑异常排查
Jhat
Oracle JDK 提供 jhat (JVM Heap Analysis Tool)命令常与 jmap 搭配使⽤,来分析 jmap ⽣成的堆转储快照。jhat内置了⼀个微型的HTTP/HTML服务器,⽣成dump⽂件的分析结果后,可以在浏览器中查看
-
jhat分析⼯作是⼀个耗时⽽且消耗硬件资源的过程
-
jhat 的分析功能相对来说⽐较简陋
模拟OOM异常自动转储快照
VM启动参数设置
-Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\Users\JunSIr\gc.hprof
如图
-相关代码
public class testJhat {
/*模拟内存泄漏OOM*/
public static void main(String[] args) {
String name = "testjhat" ;
for (int i = 0; i <1000000000 ; i++) {
name+=name ;
}
}
}
-OOM报错
实战
jhat C:\Users\JunSIr\gc.hprof
jhat指令后跟着 dump下来的文件路径
接着访问7000端口
可以复盘堆中内存使用情况
Jstack
-
Jstack (Stack Trace for Java)命令⽤于⽣成虚拟机当前时刻的线程快照(-般称为threaddump 或者 javacore ⽂件)
-
线程快照就是当前虚拟机内每⼀条线程正在执⾏的⽅法堆栈的集合,⽣成线程快照的主要⽬的是定位线程出现⻓时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的⻓时间等待等都是导致线程⻓时间停顿的常⻅原因。线程出现停顿的时候通过 jstack 来查看各个线程的调⽤堆栈,就可以知道没有响应的线程到底在后台做些什么事情,或者等待着什么资源
-模拟线程代码
public class TestThread implements Runnable{
@Override
/*线程执行方法*/
public void run() {
while (true){
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
/*创建一个线程*/
Thread thread = new Thread(new TestThread());
thread.start();
}
}
命令行敲入jps查看进程号,然后jstack -l 进程号
如图是我们模拟的进程,可以查看其线程状态以及其他一些信息,如内存起始位置,处于哪个类中
以下是利用可视化工具对内存和进程进行分析,这种可视化方法一般更为常用
JConsole
在命令行直接敲入jconsole
接下来就是无脑图形界面了
JConsole远程连接暂不介绍
实战
- 演练Jconsole内存增长过程
-代码
import java.util.ArrayList;
import java.util.List;
public class TestJConsole {
public byte[] b1 = new byte[1024*512];
public static void main(String[] args) throws InterruptedException {
System.out.println("main thread start");
Thread.sleep(10000);
allocate(10000);
}
/*模拟内存增上模型-使用JConsole*/
private static void allocate(int n) {
List<TestJConsole> jconsoleMemoryList = new ArrayList<>();
for (int i = 0; i < n; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
jconsoleMemoryList.add(new TestJConsole());
}
}
}
此代码会内存持续增长直到内存泄漏,以下是我们验证的结果
堆内存直线上升
Eden区波浪形
VisualVM
VisualVM是⼀个集成命令⾏JDK⼯具和轻量级分析功能的可视化⼯具,比Jconsole更加强大
首先我们需要在IDEA安装相关插件
-
File-> Setting-> Plugins -> Browers Repositrories 搜索 安装并重启IDEA
-
点击配置VisualVM executable执⾏路径
如:
在此点击,出现该界面,各个按钮都点点就行了
这个工具有一个强大的插件 - visual gc 可以查看堆中各年龄代内存的使用情况,如下
左边为内存占用情况,右边为内存占用随时间的函数图,可以帮助我们理解JVM的垃圾回收机制