1.检查体系进程 JPS指令
JPS检查体系进程信息 28532 G1Test 表明进程Pid28532 的进程姓名是G1Test
E:\setup\jar>jps
39024 Launcher
42832 Jps
22644
28532 G1Test
43020 RemoteMavenServer36
9756 Launcher
和咱们程序的运行是保持一致的, 咱们的程序名称便是G1Test
2.检查进程信息 ps -ef |grep xxx
Linux体系中,咱们能够运用 ps指令来检查详细的进程信息
#检查体系 java 进程信息
ps -ef |grep java
#检查详细项目的进程信息
ps -ef |grep web-gateway
履行成果
[saas@dev-119 ~]$ ps -ef |grep web-gateway
saas 7039 5764 0 14:33 pts/0 00:00:00 grep --color=auto web-gateway
root 25030 25009 0 3月27 ? 00:00:00 /bin/bash /xxx/app/web-gateway/web-gateway.sh
root 25097 25030 3 3月27 ? 17:34:15 java -server
-Dspring.profiles.active=docker
-DskipTests -Dfile.encoding=UTF-8
-Dsun.jnu.encoding=UTF-8
-Duser.timezone=GMT+8
-Djava.net.preferIPv6Addresses=false -agentlib:jdwp=transport=dt_socket,address=20112,server=y,suspend=n -Xms2g -Xmx2g -Ddubbo.registry.address=zoo1:2181,zoo2:2181
-Dspring.cloud.nacos.config.namespace=xxx
-Dsso-env=xxx
-Dspring.cloud.nacos.discovery.group=xxx
-DxxxUrl=https://sso119.devtest.vip
-DxxxUrl=https://xxx
-DxxxUrl=https://xxx
-DxxxUrl=https://xxx
-DxxxUrl=https://xxx
-jar /xxx/web-gateway/web-gateway.jar
3.jinfo pid 指令检查进程信息
咱们经过 jps 或许经过 ps-ef |grep xxx 都是为了找到进程信息,找到之后 有什么用 ? 咱们能够经过进程信息,检查进程参数 jinfo指令
#检查进程详细参数, 履行 jinfo pid进程id
jinfo 36612
履行成果
E:\setup\jar>jinfo 36612
Attaching to process ID 36612, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.181-b13
Java System Properties:
java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.181-b13
sun.boot.library.path = C:\xxxxx
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = ;
file.encoding.pkg = sun.io
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
sun.os.patch.level =
sun.java.launcher = SUN_STANDARD
user.script =
user.country = CN
user.dir = E:xxxxx
java.vm.specification.name = Java Virtual Machine Specification
java.runtime.version = 1.8.0_181-b13
java.awt.graphicsenv = sun.awt.Win32GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = C:\xxxxx
line.separator =
java.io.tmpdir = C:\xxxxx
java.vm.specification.vendor = Oracle Corporation
user.variant =
os.name = Windows 10
sun.jnu.encoding = GBK
java.library.path = xxxxx
java.class.version = 52.0
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 10.0
user.home = C:\Users\jzj
user.timezone = Asia/Shanghai
java.awt.printerjob = sun.awt.windows.WPrinterJob
file.encoding = UTF-8
java.specification.version = 1.8
user.name = jzj
java.class.path =xxxxx
java.vm.specification.version = 1.8
sun.arch.data.model = 64
sun.java.command = com.jzj.jvmtest.jvmready.G1Test
java.home = C:\xxxxx
user.language = zh
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.windows.WToolkit
java.vm.info = mixed mode
java.version = 1.8.0_181
java.ext.dirs = xxxxx
file.separator = \
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
sun.desktop = windows
sun.cpu.isalist = amd64
VM Flags:
Non-default VM flags: -XX:CICompilerCount=4 -XX:ConcGCThreads=3 -XX:G1HeapRegionSize=1048576 -XX:+HeapDumpOnOutOfMemoryError -XX:InitialHeapSize=10485760 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=10485760 -XX:MaxNewSize=6291456 -XX:MinHeapDeltaBytes=1048576 -XX:+PrintGC -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation
Command line: -verbose:gc -XX:+UseG1GC -Xms10M -Xmx10M -XX:+PrintGC -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:SurvivorRatio=8 -javaagent:E:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar=58937:E:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\bin -Dfile.encoding=UTF-8
3.1 体系变量
悉数的java体系变量等等
- java.version java版别
- user.name 用户姓名
- user.timezone = Asia/Shanghai 时区信息
- java.io.tmpdir = C:\xxxxx 临时文件寄存途径
java.home = C:\xxxxx
user.language = zh
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.windows.WToolkit
java.vm.info = mixed mode
java.version = 1.8.0_181
java.ext.dirs = xxxxx
3.2 JVM参数
VM虚拟机参数 VM Flags
- -XX:G1HeapRegionSize 每个Region的大小,单位MB,需要为1,2,4,8,16,32其一,默认是堆内存的1/2000
- -XX:InitialHeapSize=10485760 等同于 -Xms设置,表明Heap的初始化大小,即JVM启动时,堆区的最小值
- -XX:HeapDumpOnOutOfMemoryError 堆栈溢出打印OOM错误
- -XX:MaxNewSize=6291456 JVM堆区域新生代内存的最大可分配大小(PermSize不属于堆区)
- -XX:+UseG1GC 运用G1废物搜集器
- -XX:MinHeapDeltaBytes=1048576 表明当咱们要扩容或许缩容的时分,决议是否要做或许尝试扩容的时分最小扩多少
- -XX:+PrintGCDetails GC时分打印概况
- -XX:SurvivorRatio=8 年青到和survivor比例是 1:1:8 (s0:s1:Eden)
- XX:MaxHeapSize=10485760 最大的堆内存分配
VM Flags:
Non-default VM flags: -XX:CICompilerCount=4 -XX:ConcGCThreads=3 -XX:G1HeapRegionSize=1048576 -XX:+HeapDumpOnOutOfMemoryError -XX:InitialHeapSize=10485760 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=10485760 -XX:MaxNewSize=6291456 -XX:MinHeapDeltaBytes=1048576 -XX:+PrintGC -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation
4.jstat指令
jstat是JDK自带的轻量级小工具,专门用于监控JVM的GC状况,对Java应用程序的资源和功能进行实时的指令行的监控,包含了对Heap size和废物收回状况的监控,咱们先看看有哪些指令能够运用
#履行 jstat options
E:\setup\jar>jstat -options
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation
咱们对指令进行结束
- class 用于检查类加载状况的计算
- compiler 用于检查HotSpot中即时编译器编译状况的计算
- gc
用于检查JVM中堆的废物搜集状况的计算
常常运用 - gccapacity
用于检查新生代、老生代及持久代的存储容量状况
常常运用 - gcmetacapacity
显现metaspace的大小及信息
常常运用 - gcnew 用于检查新生代废物搜集的状况
- gcnewcapacity 用于检查新生代存储容量的状况
- gcold 用于检查老生代及持久代废物搜集的状况
- gcoldcapacity 用于检查老生代的容量
- gcutil
显现废物收回信息
常常运用 - gccause 显现废物收回的相关信息(同-gcutil), 一起显现最终一次仅当时正在发生的废物搜集的原因
- printcompilation 输出JIT编译的办法信息
启动程序
@Slf4j
public class G1Test {
//JVM 参数 -verbose:gc -Xms10M -Xmx10M -XX:+PrintGC -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:SurvivorRatio=8
public static void main(String[] args) throws Exception {
byte[] b = null;
for (int i = 1; i <= 20; i++) {
//设置 3M的目标
log.info("======== " + i + "次添加3M目标");
b = new byte[2 * 1024 * 1024];
Thread.sleep(3000);
}
}
}
4.1 jstat -gc pid 检查进程 GC状况
先履行 jps 找到进程PID G1Test PID是 25060
E:\setup\jar>jps
45616 Launcher
22644
25060 G1Test
44308 Jps
履行jstat -gc 25060
#履行 jstat -gc pid
E:\setup\jar>jstat -gc 25060
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
0.0 1024.0 0.0 1024.0 3072.0 0.0 6144.0 5777.7 5504.0 5088.0 640.0 565.8 2 0.003 0 0.000 0.003
#履行 jstat -gc pid 参数1(多少秒履行1次) 参数2 总共打印多少次
#履行 jstat -gc 25060 1000 3 ,表明 1000ms履行1次, 总共履行 3次
E:\setup\jar>jstat -gc 25060 1000 3
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
0.0 1024.0 0.0 1024.0 3072.0 0.0 6144.0 5777.7 5504.0 5088.0 640.0 565.8 2 0.003 0 0.000 0.003
0.0 1024.0 0.0 1024.0 3072.0 0.0 6144.0 5777.7 5504.0 5088.0 640.0 565.8 2 0.003 0 0.000 0.003
0.0 1024.0 0.0 1024.0 3072.0 0.0 6144.0 5777.7 5504.0 5088.0 640.0 565.8 2 0.003 0 0.000 0.003
咱们解释一下这些信息S0C/S1C/S0U等等代表什么意思
年青代 幸存区S0/S1 及Eden区的运用状况(单位字节Byte)
S0C | S1C | S0U | S1U | EU | EC |
---|---|---|---|---|---|
年青代幸存区From区S0的 容量Capacity | 年青代幸存区To区S1的 容量Capacity | 年青代幸存区From区S0现已运用Use的容量Capacity | 年青代幸存区To区S1的 现已运用Use的容量Capacity | 年青代Eden区的容量Capacity | 年青代Eden区现已运用Used的容量Capacity |
老时代Old区,元空间Metaspace及CCS(当时压缩类)的运用状况 (单位字节Byte)
OC | OU | MC | MU | CCSU | CCSU |
---|---|---|---|---|---|
Old老时代 容量Capacity | Old老时代现已运用Use的容量Capacity | 元空间Metaspace 容量Capacity | 元空间Metaspace现已运用Use的容量Capacity | 当时压缩类空间 容量Capacity | 当时压缩类空间现已运用Used的容量Capacity |
YoungGC,FullGC发生的次数及花费的时刻(秒/s)状况
YGC | YGCT | FGC | FGCT | GCT |
---|---|---|---|---|
从程序启动到采样,YoungGC 发生的次数 | 从程序启动到采样,YoungGC 花费的时刻 | 从程序启动到采样,FullGC 发生的次数 | 从程序启动到采样,FullGC 花费的时刻 | 从程序启动到采样,GC总共用时 |
4.2 jstat -gcutil pid 检查进程 GC废物收回状况
履行JPS找到进程PID G1Test PID 44788
E:\setup\jar>jps
22644
44788 G1Test
47492 Jps
35992 Launcher
履行 jstat -gcutil 44788 1000 10 检查废物收回状况 1000ms 打印一次, 总共打印10次
#履行 jstat -gcutil 44788 1000 10
E:\setup\jar>jstat -gcutil 44788 1000 10
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 0.00 65.24 94.24 89.56 20 0.081 4 0.037 0.118
0.00 0.00 0.00 65.24 94.24 89.56 21 0.081 4 0.037 0.118
0.00 0.00 0.00 65.35 94.24 89.56 21 0.092 4 0.037 0.129
0.00 0.00 0.00 65.35 94.24 89.56 21 0.092 4 0.037 0.129
0.00 100.00 0.00 31.89 94.24 89.56 23 0.100 5 0.037 0.137
0.00 0.00 0.00 86.70 94.24 89.56 23 0.100 5 0.049 0.149
0.00 0.00 0.00 86.70 94.24 89.56 23 0.100 5 0.049 0.149
0.00 100.00 0.00 70.10 94.24 89.56 24 0.103 5 0.049 0.152
0.00 100.00 0.00 70.10 94.24 89.56 24 0.103 5 0.049 0.152
0.00 100.00 0.00 70.10 94.24 89.56 24 0.103 5 0.049 0.152
咱们解释一下这些信息 S0/S/E/O/M/CCS/YGC/YGCT/FGC/FGCT/GCT 等代表什么意思
首先说明一点 这儿打印出来的不是实在运用的容量Byte,而是为了便利检查,运用的是 百分比占比
,愈加直观,便利定位问题
S0 | S1 | E | O | M | CCS |
---|---|---|---|---|---|
年青代幸存区From区S0 已运用占当时容量的百分比 | 年青代幸存区From区S1 已运用占当时容量的百分比 | Eden区现已运用占当时容量的百分比 | Old老时代现已运用占当时容量的百分比 | 元空间Metaspace现已运用占当时容量的百分比 | 当时压缩类空间现已运用占当时容量的百分比 |
从上面能够看出来什么问题? 咱们看下这两次打印
#履行 jstat -gcutil 44788 1000 10
E:\setup\jar>jstat -gcutil 44788 1000 10
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 0.00 65.35 94.24 89.56 21 0.092 4 0.037 0.129
0.00 100.00 0.00 31.89 94.24 89.56 23 0.100 5 0.037 0.137
- YGC从 21->23 说明1s之内发生了2次YoungGC,FGC从 4->5说明1s之内发生了1次FullGC
- YGC/FullGC后,S0区域开始向S1区域复制存活的目标,导致S1占比100%
- 说明YounGC后,需要复制的东西很多,从From转移到To区
- Old区从65%->31%, 老时代部分目标经历过FullGC后被销毁
- Metaspace 占比94.24% 元空间太小了,即将要占满
4.3 jstat -gccause pid 检查gc原因
履行JPS找到进程PID G1Test PID 44912
E:\setup\jar>jps
44912 G1Test
22644
37180 Launcher
46220 Jps
履行 jstat -gccause 44912 检查gc引起的原因
E:\setup\jar>jstat -gccause 44912
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC
0.00 0.00 0.00 86.70 94.22 89.56 13 0.045 3 0.017 0.062 Allocation Failure No GC
- LGGC 最终一次GC的原因 Allocation Failure 内存分配失败导致
- GCC 当时GC原因 No GC 为当时没有履行GC
E:\setup\jar>jstat -gccause 44912
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC
0.00 100.00 0.00 70.07 94.22 89.56 19 0.066 4 0.023 0.089 G1 Humongous Allocation No GC
- LGGC 最终一次GC的原因 G1 Humongous Allocation G1的大目标分配导致
- GCC 当时GC原因 No GC 为当时没有履行GC
至此 咱们学习了基本的JVM调优指令包含JPS检查进程,jinfo检查进程详细参数,Jstat检查JVM gc状况,特别是jstat的轻量级JVM调优小工具运用,咱们依据详细的日志,来剖析JVM发生GC的原因,进行JVM调优