JVM调优参数、命令及工具

959 阅读4分钟

1 JVM参数

有时候我们需要设置一些JVM的参数来进行JVM调优,我们常使用的的参数有两种类型

1.1 参数类型

  • Boolean类型
格式:-XX:[+-] +或-表示启用或者禁用name属性
比如:-XX:+UseConcMarkSweepGC 表示启用CMS类型的垃圾回收器
-XX:+UseG1GC 表示启用G1类型的垃圾回收器
  • 非Boolean类型
格式:-XX=表示name属性的值是value
比如:-XX:MaxGCPauseMillis=500
另外还有些参数比较特殊:
-Xms1000等价于-XX:InitialHeapSize=1000
-Xmx1000等价于-XX:MaxHeapSize=1000
-Xss100等价于-XX:ThreadStackSize=100

1.2 查看参数

我们可以在命令行输入以下命令
java -XX:+PrintFlagsFinal -version > flags.txt

我们也可以在IDE上配置这个参数,以Idea为例

启动之后:

另外,需要说明的是“=”表示默认值,“:=”标识被用户或者JVM修改后的值

1.3 设置参数的方式

  • 开发工具中设置比如IDEA,eclipse
  • 运行jar包的时候:java -XX:+UseG1GC xxx.jar
  • web容器比如tomcat,可以在脚本中的进行设置
  • 通过jinfo实时调整某个java进程的参数(参数只有被标记为manageable的flags可以被实时修改)

1.4 实践

  1. 设置堆内存大小和参数打印 -Xmx100M -Xms100M -XX:+PrintFlagsFinal

   2 .查询+PrintFlagsFinal的值

  3. 查询堆内存大小MaxHeapSize

1.5 常用参数的含义

2 常用命令

2.1 jps

查看进程
The jps command lists the instrumented Java HotSpot VMs on the target system.
The command is limited to reporting information on JVMs for which it has the
access permissions.

2.2 jinfo

实时查看和调整jvm的参数
  1. 查看
jinfo -flag name PID 查看某个java进程的name属性的值
jinfo -flag MaxHeapSize PID
jinfo -flag UseG1GC PID

  2. 修改

参数只有被标记为manageable的flags可以被实时修改
jinfo -flag [+|-] PID
jinfo -flag = PID

 3. 查看曾经赋值过的参数

jinfo -flags PID

2.3 jstat

可以查看虚拟机的性能,类装载和GC信息
jstat -class PID 1000 10   查看某个java进程的类装载信息,每1000毫秒输出一次,共输出10
次

jstat -gc PID 1000 10 查看gc收集信息

2.4 jstack

用于查看线程堆栈的信息
jstack pid

下面以一个死锁的例子进行分析
public class DeadLock {
    static Object obj1 = new Object();
    static Object obj2 = new Object();

    public static void main(String[] args) {

        Thread t1 = new Thread(()->{
           synchronized (obj1) {
               System.out.println(Thread.currentThread().getName() + "获得obj1的锁");
               synchronized (obj2) {
                   System.out.println(Thread.currentThread().getName() + "获得obj2的锁");
               }
           }
        });
        Thread t2 = new Thread(()->{
            synchronized (obj2) {
                System.out.println(Thread.currentThread().getName() + "获得obj2的锁");
                synchronized (obj1) {
                    System.out.println(Thread.currentThread().getName() + "获得obj1的锁");
                }
            }
        });
        t1.start();
        t2.start();
    }

}
以上代码就是典型的死锁案例,线程T1获得锁obj1,线程T2获取锁obj2,而他们又想获取对方持有且未释放的锁,就会造成死锁。用jstack命令查看如下:

拉到最下面可发现

2.5 jmap

该命令是为了生成堆转储快照,执行一下命令打印堆内存相关信息
jmap -heap PID

我们也可以将这个对信息dump出来
jmap -dump:format=b,file=heap.hprof PID
在对应的目录可以找到这个文件,该文件需要使用指定的工具进行分析

我们也可以让他在堆内溢出的时候自动dump出来,只需要配置以下参数
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof
编写一个方法,把初始堆和最大堆的参数配小
@RestController
public class HeapController {
    List list=new ArrayList();
    @GetMapping("/heap")
    public String heap() throws Exception{
        System.out.println("开始");
        while(true){
            list.add(new Person());
            Thread.sleep(1);
        }
    }
}

3 工具

虽说用命令可以查看JVM相关的信息,但是还是不太方便,这时候用图形化界面的形式可能会更好。

3.1 jconsole

JConsole工具是JDK自带的可视化监控工具。查看java应用程序的运行概况、监控堆信息、永久区使用情况、类加载情况等。只需要在命令行输入jconsole即可,如下图,我们只需要选择对应的进程即可

3.2 jvisualvm

也是一个不错的监控工具,可监控Java进程的CPU,类,线程等
下载地址https://visualvm.github.io/download.html

远程连接方式:
例如 java -jar test.jar,加入三个参数
-Dcom.sun.management.jmxremote.port=端口号
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
如:
java -Dcom.sun.management.jmxremote.port=端口号 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar test.jar

3.3 Arthas

阿里巴巴旗下的Java诊断工具
下载安装方式
curl -O https://alibaba.github.io/arthas/arthas-boot.jar

java -jar arthas-boot.jar PID

此时进入到arthas命令操作,我们可以输入arthas的命令进行的操作,例如 dashboard

具体命令可以查阅资料
version:查看arthas版本号
help:查看命名帮助信息
cls:清空屏幕
session:查看当前会话信息
quit:退出arthas客户端
---
dashboard:当前进程的实时数据面板
thread:当前JVM的线程堆栈信息
jvm:查看当前JVM的信息
sysprop:查看JVM的系统属性
---
sc:查看JVM已经加载的类信息
dump:dump已经加载类的byte code到特定目录
jad:反编译指定已加载类的源码
---
monitor:方法执行监控
watch:方法执行数据观测
trace:方法内部调用路径,并输出方法路径上的每个节点上耗时
stack:输出当前方法被调用的调用路径

3.4 MAT

Java堆分析器,对dump文件进行分析,查找内存泄露
下载地址
https://www.eclipse.org/mat/downloads.php

里面有几个操作可以关注下:
  • Histogram
Histogram可以列出内存中的对象,对象的个数及其大小
  • Leak Suspects
查找并分析内存泄漏的可能原因
  • Top Consumers
列出大对象