目录
JVM 参数
五大常用命令
jps
jinfo
jstat
jstack 堆栈信息
jmap
常用工具
jconsole
jvisualvm
MAT
JVM 参数
标准参数
不会随着我们JDK 变化而变化版本
java -help 查看
-X 参数(非标准参数)
在jdk版本中存在,可能会随着版本变更移除
java -Xint -version 解释执行
java -Xcomp -version第一次使用就编译成本地代码
java -Xmixed -version混合模式,JVM自己来决定
-XX参数(调优)
JVM调优使用用到最多的参数
也是非标准参数,可能会随着版本变更移除,主要用于调优和DEBUG
Boolean 类型
-XX:[+-]<name>
-XX:+UseConcMarkSweepGC 表示使用CMS类型的垃圾回收器
-XX:+UseG1GC 表示启用一个G1垃圾收集器
非 Boolean 类型
-XX:<name>=<value>
-XX:MaxGCPauseMillis=500 表示最大的停顿时间ms
常用的参数含义
参数 | 含义 | 说明 |
-XX:InitialHeapSize=100M | 初始化堆大小 | 简写-Xms100M |
-XX:MaxHeapSize=100M | 最大堆大小 | 简写-Xmx100M |
-XX:NewSize=20M | 设置年轻代的大小 | |
-XX:MaxNewSize=50M | 年轻代最大大小 | |
-XX:OldSize=50M | 设置老年代大小 | |
-XX:MetaspaceSize=50M | 设置方法区大小 | |
-XX:MaxMetaspaceSize=50M | 方法区最大大小 | |
-XX:+UseParallelGC | 使用UseParallelGC | 新生代,吞吐量优先 |
-XX:+UseParallelOldGC | 使用UseParallelOldGC | 老年代,吞吐量优先 |
-XX:+UseConcMarkSweepGC | 使用CMS | 老年代,停顿时间优先 |
-XX:+UseG1GC | 使用G1GC | 新生代,老年代,停顿时间优先 |
-XX:NewRatio | 新老生代的比值 | 比如-XX:Ratio=4,则表示新生代:老年代=1:4,也就是新生代占整个堆内存的1/5 |
-XX:SurvivorRatio | 两个S区和Eden区的比值 | 比如-XX:SurvivorRatio=8,也就是(S0+S1):Eden=2:8,也就是一个S占整个新生代的1/10 |
-XX:+HeapDumpOnOutOfMemoryError | 启动堆内存溢出打印 | 当JVM堆内存发生溢出时,也就是OOM,自动生成dump文件 |
-XX:HeapDumpPath=heap.hprof | 指定堆内存溢出打印目录 | 表示在当前目录生成一个heap.hprof文件 |
XX:+PrintGCDetails - | 打印出GC日志 | 可以使用不同的垃圾收集器,对比查看GC情况 |
XX:+PrintGCTimeStamps | ||
XX:+PrintGCDateStamps | ||
Xloggc:$CATALINA_HOME/logs/gc.log | ||
-Xss128k | 设置每个线程的堆栈大小 | 一个进程内的线程数经验值是3000-5000最佳 |
-XX:MaxTenuringThreshold=6 | 提升年老代的最大临界值 | 默认值为 15 |
-XX:InitiatingHeapOccupancyPercent | 启动并发GC周期时堆内存使用占比 | G1之类的垃圾收集器用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的使用比. 值为 0 则表示”一直执行GC循环”. 默认值为 45. |
-XX:G1HeapWastePercent | 允许的浪费堆空间的占比 | 默认是10%,如果并发标记可回收的空间小于10%,则不会触发MixedGC。 |
-XX:MaxGCPauseMillis=200ms | G1最大停顿时间 | 暂停时间不能太小,太小的话就会导致出现G1跟不上垃圾产生的速度。最终退化成Full GC。所以对这个参数的调优是一个持续的过程,逐步调整到最佳状态。 |
-XX:ConcGCThreads=n | 并发垃圾收集器使用的线程数量 | 默认值随JVM运行的台不同而不同 |
-XX:G1MixedGCLiveThresholdPercent=65 | 混合垃圾回收周期中要包括的旧区域设置占用率阈值 | 默认占用率为 65% |
-XX:G1MixedGCCountTarget=8 | 设置标记周期完成后,对存活数据上限为G1MixedGCLIveThresholdPercent的旧区域执行混合垃圾回收的目标次数 | 默认8次混合垃圾回收,混合回收的目标是要控制在此目标次数以内 |
-XX:G1OldCSetRegionThresholdPercent=1 | 描述Mixed GC时,Old Region被加入到CSet中 | 默认情况下,G1只把10%的Old Region加入到CSet中 |
其他参数
-Xms100M等价于-XX:InitialHeapSize=100M 堆的初始化大小
-Xmx100M等价于-XX:MaxHeapSize=100M 堆的最大内存
-Xss100k等价于-XX:ThreadStackSize=100k 虚拟机栈的大小 默认是1m
查看参数
java -XX:+PrintFlagsFinal -version
需要注意的是 = 等于默认值, := 表示被用户修改或者JVM 修改过值
一般要设置参数,可以先查看一下当前参数是什么,然后进行修改
manageable 类型是代表 可以热修改
设置参数的方式
1.开发工具
IDEA 、Eclipse 在run configuration 里设置VM option
运行jar包, java -XX:+UseG1GC xxx.jar
2.线上环境
web容器:Tomcat, startup.sh -> catalina.sh(卡特琳娜) 里设置JVM 参数
jsp + jinfo 查看某个java进程的参数,然后再调整设置
3.真实调优
java -XX:+UseG1GC xxx.jar
单位运算
1Byte(字节) = 8位
1kb = 1024 个(字节)
五大常用命令
jps
查看java进程id
查看当前系统上,正在运行的java 进程 id列表和运行的类全限定名
jinfo
查看参数
1.实时查看某个进程id的jvm 参数
2.查看某个进程id的所有jvm参数
3.修改我们可以 manageable 热更新的参数
jinfo -flag name = value PID
jinfo -flag [+|-] name PID
jinfo -flag = PID
jstat
查看性能
类加载、内存、垃圾收集情况、 JIT 实时编译的运行时数据
虚拟机统计信息监控工具,本地或者远程[1]虚拟机进程中的类加载、内存、垃
圾收集、即时编译等运行时数据
jstat <option> [-t] [-h] <pid> <interval> <count>
jstat [ option <pid> [interval[s|ms] [count]] ]
protocol : //pid@hostname: port / servername
参数解释:
option 参数 | 解释 |
-class | 显示ClassLoad的相关信息 |
-compiler | 显示JIT编译的相关信息 |
-gc | 显示和gc相关的堆信息- |
-gccapacity | 显示各个代的容量以及使用情况 |
-gccause | 显示垃圾回收的相关信息(通-gcutil),同时显示最后一次或当前正在发生的垃圾回收的诱因 |
-gcnew | 显示新生代的信息 |
-gcnewcapacity | 显示新生代大小和使用情况 |
-gcold | 显示老年代和永久代的信息 |
-gcoldcapacity | 显示老年代的大小 |
-gcpermcapacity | 显示永久代的大小 |
-gcutil | 显示垃圾收集信息 |
printcompilation | 输出JIT编译的方法信息 |
参数 | 解释 |
-t | 可以在打印的列上加上Timestamp列,用于显示系统运行的时间 |
-h | 可以在周期性数据的时候,可以在指定输出多少行以后输出一次表头 |
interval | 执行每次的间隔时间,单位为毫秒 |
count | 用于指定输出多少次记录,缺省则会一直打印 |
1.查看类装载信息
jstat -class PID 1000 1 查看某个java进程的类装载信息,每1000毫秒输出一
次,共输出1次
参数 | 解析 |
Loaded | 加载类的数量 |
Bytes | 加载类合计大小 |
UnLoaded | 卸载类的数量 |
Bytes | 卸载类合计大小 |
Time | 表示加载和卸载类总共耗时 |
2.查看垃圾收集信息
jstat -gc PID 1000 10
参数 | 解析 |
S0C | Survivor0(幸存者0区)大小(KB) |
S1C | Survivor1(幸存者1区)大小(KB) |
S0U | Survivor0(幸存者0区)已使用大小(KB) |
S1C | Survivor1(幸存者1区)以使用大小(KB) |
EC | Eeden(伊甸区)大小(KB) |
EU | Eden(伊甸区)已使用大小(KB) |
OC | 老年代大小(KB) |
OU | 老年代已使用大小 (KB) |
OC | 老年代大小(KB) |
OU | 老年代已使用大小(KB) |
PC | Perm永久代大小(KB) |
PU | Perm永久代已使用大小(KB) |
YGC | 新生代GC个数 |
YGCT | 新生代GC的耗时(秒 |
FGC | Full GC次数 |
FGCT | Full GC耗时(秒) |
GCT | GC总耗时(秒) |
C | Capacity 容量 |
U | Used 已使用的意思 |
P | permanent 永久代 |
S | Survivor 幸存者 |
Y | Young |
T | time 时间 |
E | Eden |
jstack 堆栈信息
查看线程堆栈信息
jstack pid
查看线程堆栈
DeadLockDemo
//运行主类
public class DeadLockDemo {public static void main(String[] args) {DeadLock d1=new DeadLock(true);DeadLock d2=new DeadLock(false);Thread t1=new Thread(d1);Thread t2=new Thread(d2);t1.start();t2.start();}}
//定义锁对象
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 堆内存相关信息
要是在发生堆内存溢出的时候,能自动dump出该文件就好了
一般在开发中,JVM参数可以加上下面两句,这样内存溢出时,会自动dump出该文件
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof
在服务器
在tomcat启动参数中加入两个参数
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/export/tomcat/xxx/xx/heap.hprof
在排查的的时候
一般dump下来的文件可以结合工具来分析,这块后面再说。
jmap -dump:format=b,file=heap.hprof 44808
-Xmx20M -Xms20M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof
启动,然后访问 localhost:9090/heap
jmap -dump:format=b,file=heap.hprof 44808
常用工具
jconsole、jvisualvm、MAT 在分析Dump文件的时候用
GC Viewer 分析GC日志
jconsole
Jconsole工具是JDK自带的可视化监控工具。查看java应用程序的运行情况、监控堆信息、永久区使用情况、类加载情况等等。
命令行中输入:jconsole
jvisualvm
监控本地java进程
可监控本地java进程的CPU,类,线程等等。
监控远端java进程
比如监控客户端的tomcat,演示部署在阿里云服务器上的tomcat
(1)在visualvm中选中“远程”,右击“添加”
(2)主机名上写服务器的ip地址,比如31.100.39.63,然后点击“确定”
(3)右击该主机“31.100.39.63”,添加“JMX”[也就是通过JMX技术具体监控远端服务器哪个Java进程]
(4)要想让服务器上的tomcat被连接,需要改一下 bin/catalina.sh 这个文件
注意下面的8998不要和服务器上其他端口冲突
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=31.100.39.63 -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 文件
jmxremote.password 文件
授予权限 : chmod 600 *jmxremot*
(6)将连接服务器地址改为公网ip地址
(7)设置上述端口对应的阿里云安全策略和防火墙策略
(8)启动tomcat,来到bin目录
(9)查看tomcat启动日志以及端口监听
(10)查看8998监听情况,可以发现多开了几个端口
(11)在刚才的JMX中输入8998端口,并且输入用户名和密码则登录成功
guest readonly manager readwrite
guest guest manager manager
hostname -i 查看输出情况 ip 127.0.0.1 vim /etc/hosts ip ./startup.sh
tail -f ../logs/catalina.out lsof -i tcp:8080
lsof -i:8998 得到PID netstat -antup | grep PID
端口:8998 用户名:manager 密码:manager
MAT
Java堆分析器,用于查找内存泄漏
Heap Dump,称为堆转储文件,是Java进程在某个时间内的快照
获取Dump文件
手动
jmap -dump:format=b,file=heap.hprof 44808
自动
idea设置VM参数、或者运行jar包时 设置
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof
使用MAT
Histogram
Histogram [ˈhɪstəɡræm] 柱状图 :可以列出内存中的对象,对象的个数及其大小
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[li:k] Suspects [səˈspekts]
查找并分析内存泄漏的可能原因
Reports--->Leak Suspects--->Details