# 一、JVM参数
## 1.1 标准参数
-version -help -server -cp
## 1.2 -X参数
非标准参数,也就是在JDK各个版本中可能会变动
-Xint 解释执行 -Xcomp 第一次使用就编译成本地代码 -Xmixed 混合模式,JVM自己来决定
## 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修改后的值
一般需要设置参数,可以先查下当前参数是什么,然后再进行修改
## 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 常用参数的含义
# 二、常用命令
## 2.1 jps
查看java进程
## 2.2 jinfo
1、实时查看
`jinfo -flag name PID 查看某个java进程的name属性的值`
jinfo -flag MaxHeapSize PID jinfo -flag UseG1GC PID
2、调整JVM配置参数
参数只有被标记为manageable的flags可以被实时修改
jinfo -flag \[+|-\] PID jinfo -flag = PID
3、查看曾经赋过值的一些参数
`jinfo -flags PID`
## 2.3 jstat
1、查看虚拟机性能统计信息
2、查看java进程的类装载信息
jstat -class PID 1000 10 查看某个java进程的类装载信息,每1000毫秒输出一次,共输出10 次
3、查看垃圾收集信息
`jstat -gc PID 1000 10`
## 2.4 jstack
1、查看线程堆栈信息
`jstack PID`
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方法的结果
**jstack分析**
把打印信息拉到最后可以发现
## 2.5 jmap
1、生成堆转存储快照
2、打印出堆内存相关信息
-XX:+PrintFlagsFinal -Xms300M -Xmx300M jmap -heap PID
3、dump堆内存相关信息
jmap -dump:format=b,file=heap.hprof PID jmap -dump:format=b,file=heap.hprof 44808
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
(11)在刚才的JMX中输入8998端口,并且输入用户名和密码则登录成功
端口:8998 用户名:manager 密码:manager
## 3.3 阿里的Arthas
Arthas是阿里巴巴开源的Java诊断工具,采用命令行交互模式,是排查jvm相关问题的利器。
**github:** https://github.com/alibaba/arthas
下载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/