JVM参数详解

# 一、JVM参数

## 1.1 标准参数

-version  -help  -server  -cp  

如何优雅的学习JVM,挑战全网最详细的JVM参数详解

 

## 1.2 -X参数

非标准参数,也就是在JDK各个版本中可能会变动

-Xint   解释执行  -Xcomp  第一次使用就编译成本地代码  -Xmixed  混合模式,JVM自己来决定  

JVM参数详解_第1张图片

 

## 1.3 -XX参数

使用得最多的参数类型,非标准化参数,相对不稳定,主要用于JVM调优和Debug

a.Boolean类型  格式:-XX:\[+-\]      +或-表示启用或者禁用name属性  比如:-XX:+UseConcMarkSweepGC  表示启用CMS类型的垃圾回收器  -XX:+UseG1GC       表示启用G1类型的垃圾回收器  b.非Boolean类型  格式:-XX= 表示name属性的值是value  比如:-XX:MaxGCPauseMillis=500  

## 1.4 其它参数

-Xms1000等价于 -XX:InitialHeapSize=1000  -Xmx1000等价于 -XX:MaxHeapSize=1000  -Xss1000等价于 -XX:ThreadStackSize=1000  

这一块内容也相当于-XX类型的参数

## 1.5 查看参数

java -XX:+PrintFlagsFinal -version > flags.txt

如何优雅的学习JVM,挑战全网最详细的JVM参数详解

 

JVM参数详解_第2张图片

 

上图值得注意的是“=”表示默认值,“:=”表示被用户或JVM修改后的值

一般需要设置参数,可以先查下当前参数是什么,然后再进行修改

## 1.6 设置参数的方式

* 开发工具中进行设置IDEA、eclipse

* 运行jar包的时候:java -XX:+UseG1GC xxx.jar

* Web容器比如Tomcat,可以在脚本中进行设置

* 通过**jinfo**命令实时调整某个java进程的参数(参数只有被标记为**manageable**的flags可以被实时修改

# 1.7 单位换算和实践

1Byte(字节)=8bit(位)  1KB=1024Byte(字节)  1MB=1024KB  1GB=1024MB  1TB=1024GB  

1、设置堆内存大小和参数打印

-Xmx100M -Xms100M -XX:+PrintFlagsFinal

2、查询+PrintFlagsFinal

:=true

3、查询堆内存大小MaxHeapSize

:= 104857600

4、换算

104857600(Byte)/1024=102400(KB)  102400(KB)/1024=100(MB)  

5、结论

`104857600是字节单位`

# 1.8 常用参数的含义

JVM参数详解_第3张图片

 

# 二、常用命令

## 2.1 jps

查看java进程

JVM参数详解_第4张图片

 

## 2.2 jinfo

1、实时查看

`jinfo -flag name PID 查看某个java进程的name属性的值`

jinfo -flag MaxHeapSize PID  jinfo -flag UseG1GC PID  

JVM参数详解_第5张图片

 

2、调整JVM配置参数

参数只有被标记为manageable的flags可以被实时修改

jinfo -flag \[+|-\] PID  jinfo -flag = PID  

3、查看曾经赋过值的一些参数

`jinfo -flags PID`

JVM参数详解_第6张图片

 

## 2.3 jstat

1、查看虚拟机性能统计信息

2、查看java进程的类装载信息

jstat -class PID 1000 10 查看某个java进程的类装载信息,每1000毫秒输出一次,共输出10 次

JVM参数详解_第7张图片

 

3、查看垃圾收集信息

`jstat -gc PID 1000 10`

如何优雅的学习JVM,挑战全网最详细的JVM参数详解

 

## 2.4 jstack

1、查看线程堆栈信息

`jstack PID`

JVM参数详解_第8张图片

 

2、排查死锁的案例

示例代码:

public class DeadLockDemo {    public static void main(String\[\] args) {          DeadLock deadLock1 = new DeadLock(true);          DeadLock deadLock2 = new DeadLock(false);          Thread thread1 = new Thread(deadLock1);          Thread thread2 = new Thread(deadLock2);          thread1.start();          thread2.start();      }    static class MyLock {          public static Object obj1 = new Object();          public static Object obj2 = new Object();      }    static 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() + "如果获得obj1的锁");                          synchronized (MyLock.obj2) {                              System.out.println(Thread.currentThread().getName() + "如果获得obj2的锁");                          }                      }                  }              }else {                  while (true) {                      synchronized (MyLock.obj2) {                          System.out.println(Thread.currentThread().getName() + "否则获得obj2的锁");                          synchronized (MyLock.obj1) {                              System.out.println(Thread.currentThread().getName() + "否则获得obj1的锁");                          }                      }                  }              }          }      }  }  

运行main方法的结果

JVM参数详解_第9张图片

 

**jstack分析**

JVM参数详解_第10张图片

 

把打印信息拉到最后可以发现

JVM参数详解_第11张图片

 

## 2.5 jmap

1、生成堆转存储快照

2、打印出堆内存相关信息

-XX:+PrintFlagsFinal -Xms300M -Xmx300M  jmap -heap PID  

JVM参数详解_第12张图片

 

3、dump堆内存相关信息

jmap -dump:format=b,file=heap.hprof PID  jmap -dump:format=b,file=heap.hprof 44808  

JVM参数详解_第13张图片

 

4、要是能在发生堆内存溢出的时候,能自动dump出该文件就好了

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

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

# 三、常用工具

## 3.1 jconsole

JConsole工具是JDK自带的可视化监控工具。查看java应用程序的运行概况、监控堆信息、永久区使用情况、类加载情况等。

命令行中输入:jconsole

## 3.2 jvisualvm

**1、可以监控本地的java进程的CPU,类,线程等**

**2、可以监控远端tomcat,演示部署在阿里云服务器上的tomcat**

(1)在visualvm中选中“远程”,右击“添加”(2)主机名上写服务器的ip地址,比如39.105.32.236,然后点击“确定”(3)右击该主机“39.105.32.236”,添加“JMX”[也就是通过JMX技术具体监控远端服务器哪个Java进程](4)要想让服务器上的tomcat被连接,需要改一下 bin/catalina.sh 这个文件

注意下面的8998不要和服务器上其他端口冲突

JAVA\_OPTS="$JAVA\_OPTS -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=39.105.32.236 -Dcom.sun.management.jmxremote.port=8998 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access -Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password"  

(5)在 ../conf 文件中添加两个文件jmxremote.access和jmxremote.password

**jmxremote.access 文件**

guest readonly  manager readwrite  

**jmxremote.password 文件**

guest guest  manager manager  

授予权限 : chmod 600 *jmxremot*

(6)将连接服务器地址改为公网ip地址

hostname -i 查看输出情况172.17.6.246 172.17.0.1vim /etc/hosts172.17.6.246 339.105.32.236

(7)设置上述端口对应的阿里云安全策略和防火墙策略

firewall-cmd --add-port=8080/tcp --permanent  firewall-cmd --add-port=8998/tcp --permanent  systemctl restart firewalld  

(8)启动tomcat,来到bin目录

./startup.sh

(9)查看tomcat启动日志以及端口监听

tail -f ../logs/catalina.out  lsof -i tcp:8080  

(10)查看8998监听情况,可以发现多开了几个端口

lsof -i:8998  得到PID  netstat -antup | grep PID  

如何优雅的学习JVM,挑战全网最详细的JVM参数详解

 

(11)在刚才的JMX中输入8998端口,并且输入用户名和密码则登录成功

端口:8998  用户名:manager  密码:manager  

## 3.3 阿里的Arthas

Arthas是阿里巴巴开源的Java诊断工具,采用命令行交互模式,是排查jvm相关问题的利器。

**github:** https://github.com/alibaba/arthas

JVM参数详解_第14张图片

 

下载arthas-boot.jar,然后用java -jar的方式启动:

curl -O https://alibaba.github.io/arthas/arthas-boot.jar  java -jar arthas-boot.jar  

打印帮助信息:

`java -jar arthas-boot.jar -h`

常用命令

具体每个命令怎么使用,大家可以自己查阅资料!

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堆分析器,用于查找内存泄漏

Heap Dump,称为堆转储文件,是Java进程在某个时间内的快照

**下载地址:** https://www.eclipse.org/mat/downloads.php

1、Dump信息包含的内容

* All Objects

Class, fields, primitive values and references

* All Classes

Classloader, name, super class, static fields

* Garbage Collection Roots

Objects defined to be reachable by the JVM

* Thread Stacks and Local Variables

The call-stacks of threads at the moment of the snapshot, and per-frame information about localobjects

2、获取Dump文件

* 手动

`jmap -dump:format=b,file=heap.hprof 44808`

自动

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

3、使用

* Histogram

Histogram可以列出内存中的对象,对象的个数及其大小

Class Name:类名称,java类名  Objects:类的对象的数量,这个对象被创建了多少个  Shallow Heap:一个对象内存的消耗大小,不包含对其他对象的引用  Retained Heap:是shallow Heap的总和,即该对象被GC之后所能回收到内存的总和  

右击类名--->List Objects--->with incoming references--->列出该类的实例

右击Java对象名--->Merge Shortest Paths to GC Roots--->exclude all ...--->找到GC Root以及原因

* Leak Suspects

查找并分析内存泄漏的可能原因

`Reports--->Leak Suspects--->Details`

* Top Consumers

列出大对象

## 3.5 GC日志分析工具

要想分析日志的信息,得先拿到GC日志文件才行,所以得先配置一下

根据前面参数的学习,下面的配置很容易看懂

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps  -Xloggc:gc.log  

* 在线工具

https://gceasy.io/

你可能感兴趣的:(收获)