JVM 学习笔记 (六)

时间:2022-07-22
本文章向大家介绍JVM 学习笔记 (六),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

前言:

  前几篇文章和大家介绍了JVM中的内存模型以及垃圾回收器,今天和大家一起学习一下在平时jvm调优的过程中常用的参数以及命令。

JVM中-XX类型的参数:

  我们经常用到的-XX类型有两种定义:

1. a.Boolean类型

格式: -XX:[+-]<name> +或-表示启用或者禁用name属性

比如: -XX:+UseConcMarkSweepGC 表示启用CMS类型的垃圾回收器

   -XX:+UseG1GC 表示启用G1类型的垃圾回收器

2. b.非Boolean类型

格式: -XX<name>=<value>表示name属性的值是value

比如: -XX:MaxGCPauseMillis=500

还有一些常用的参数赋值方式,比如:

-Xms1000等价于-XX:InitialHeapSize=500 (设置JVM初始化时堆内存大小)

-Xmx1000等价于-XX:MaxHeapSize=1000 (设置JVM最大堆内存大小)

-Xss100等价于-XX:ThreadStackSize=100 (设置jvm中每个线程内存大小)

设置JVM参数的方式

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

  这里不详细展开讨论。

下图是网友整理好的JVM常用参数,分享给大家:

常用命令:

  • jps

  查看java进程

  • jinfo

  实时查看和调整JVM配置参数。例如: jinfo -flag name PID 查看某个java进程的name属性的值。

jinfo -flag MaxHeapSize PID

jinfo -flag UseG1GC PID

  • jstat

  查看虚拟机性能统计信息,比如查看类装载信息:jstat -class PID 1000 10 查看某个java进程的类装载信息,每1000毫秒输出一次,共输出10次。

  • jstack

  查看线程堆栈信息,比如: jstack PID。

这里值得说明的是,我们可以用这个命令来排查项目中的一些死锁情况,下面就模拟死锁场景:

代码如下:

//定义锁对象
class MyLock {
    public static Object obj1 = new Object();
    public static Object obj2 = new Object();
}

//死锁代码
class DeadLock implements Runnable {
    private boolean flag;

    DeadLock(boolean flag) {
        this.flag = flag;
    }

    public void run() {
        if (flag) {
            while (true) {
                synchronized (MyLock.obj1) {
                    System.out.println(Thread.currentThread().getName() + "----if 获得obj1锁");
                    synchronized (MyLock.obj2) {
                        System.out.println(Thread.currentThread().getName() + "--- -if获得obj2锁");
                    }
                }
            }
        } else {
            while (true) {
                synchronized (MyLock.obj2) {
                    System.out.println(Thread.currentThread().getName() + "----否则 获得obj2锁");
                    synchronized (MyLock.obj1) {
                        System.out.println(Thread.currentThread().getName() + "--- -否则获得obj1锁");
                    }
                }
            }
        }
    }
}

运行结果如下:

去看看该进程的堆栈信息:

这里的信息可以看出两个线程都在等对方解锁对象,导致线程死锁。

  • jmap

  打印出堆内存相关信息: jmap -heap PID

  dump出堆内存相关信息: jmap -dump:format=b,fifile=heap.hprof PID

  如何设置当发生堆内存溢出的时候,能自动dump出该文件呢,这样便可以进行快速定位:

一般在开发中,JVM参数可以加上下面两句,这样内存溢出时,会自动dump出该文件

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof