茂展的分享博客

深入学习JVM调优(一)

深入学习JDK调优

非标准化参数

X类型参数

-Xint: 解释执行
-Xcomp: 第一次使用就编译成本地代码
-Xmixed: 混合模式,JVM自己决定是否编译成本地代码
X类型的参数

扩展

解释执行:将编译好的字节码一行一行地翻译为机器码执行。
编译执行:以方法为单位,将字节码一次性翻译为机器码后执行。

在编译示时期,我们通过将源代码编译成.class ,配合JVM这种跨平台的抽象,屏蔽了底层计算机操作系统和硬件的区别,实现了“一次编译,到处运行” 。 而在运行时期,目前主流的JVM 都是混合模式(-Xmixed),即解释运行 和编译运行配合使用。以 Oracle JDK提供的HotSpot虚拟机为例,在HotSpot虚拟机中,提供了两种编译模式:解释执行 和 即时编译(JIT,Just-In-Time)。解释执行即逐条翻译字节码为可运行的机器码,而即时编译则以方法为单位将字节码翻译成机器码(上述提到的“编译执行”)。前者的优势在于不用等待,后者则在实际运行当中效率更高。

XX类型参数

主要用途:jvm调优

Boolean类型

格式: -XX:[+-]< name>表示启用或者禁用name属性,其中+表示启用,-表示禁用
例如: -XX:+UseConcMarkSweepGC 启用CMS垃圾收集器;-XX:+UseG1GC 启用G1垃圾收集器

非Boolean类型

格式: -XX:< name>=< value>表示name属性的值是value
比如: -XX:MaxGCPauseMillis=500表示GC垃圾收集最大停顿时间是500毫秒

-Xms: jvm的初始内存大小,也可以成为最小内存大小
-Xmx: jvm的最大内存大大小
-Xss: 设置线程堆栈的大小

JVM运行时参数

-XX:+PrintFlagsInitial 查看初始值

-XX:+PrintFlagsFinal 查看最终值

-XX:+UnlockExperimentalVMOptions 解锁实验参数

-XX:+UnlockDiagnosticVMOptions 解锁诊断参数

-XX:+PrintCommandLineFlags 打印命令行参数

详解

-XX:+PrintFlagsFinal 查看最终值
然后执行java -XX:PrintFlagsFinal -version结果得到有 := 和 =的键值对,其中 := 表示 被用户或者JVM修改后的值,= 表示默认值

此时运行的结果表示是当前命令执行的所在线程的参数值
当前所有线程的参数值

jps

专门用来查询java进程的命令,类似于linux中的ps命令
其中 jps -l 能够查看到具体的进程中的全类名
jps打印

刚刚我们通过jps查到对用的进程号,然后我们通过jinfo -flags 进程号 打印出所有的参数变量

jstat

用来查看JVM的统计信息

  1. 类加载 2. 垃圾收集 3. JIT编译
    我们首先使用jps找到对应的进程id,
    然后我们使用 jstat -class id 毫秒数 数量 打印出对应的统计信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
F:\jvm>jstat -class 16108
Loaded Bytes Unloaded Bytes Time
677 1339.9 0 0.0 0.54

F:\jvm>jstat -compiler 16108
Compiled Failed Invalid Time FailedType FailedMethod
114 0 0 0.08 0

//其中S0C S1C S0U S1U表示survior区的总量和使用量
// EC EU OC OU 分别表示 Eden区和old区的总量和使用量
//GCT 总的垃圾回收时间
// YGC YGCT FGC FGCT 分别表示minor gc的次数和时间 Full gc的次数和时间
F:\jvm>jstat -gc 16108
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
512.0 512.0 504.0 0.0 2048.0 587.3 129536.0 638.1 4864.0 3810.5 512.0 427.0 4 0.005 0 0.000 0.005

其中 Loaded 加载的个数

jmap + MAT 定位内存溢出

出现内存泄露,需要我们导出内存映像文件,有两种方式
1 内存溢出自动导出
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./

在系统运行的时候配置上面两个参数,控制台打印出

1
2
3
4
5
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to ./\java_pid18408.hprof ...
Heap dump file created [48277884 bytes in 0.389 secs]
Exception in thread "http-nio-80-exec-3" java.lang.OutOfMemoryError: GC overhead limit exceeded
Exception in thread "http-nio-80-exec-1" java.lang.OutOfMemoryError: GC overhead limit exceeded

然后我们会在项目所在目录找到 java_pid18408.hprof 文件

2 使用jmap命令手动导出
首先我们使用jps -l 得到对应进程的进程号

1
2
3
F:\jvm>jmap -dump:format=b,file=heap.hprof 18408
Dumping heap to F:\jvm\heap.hprof ...
Heap dump file created

我们使用jmap -heap 进程号,可以得到对应堆内存数据配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
F:\jvm>jmap -heap 18408
Attaching to process ID 18408, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.11-b03

using thread-local object allocation.
Parallel GC with 8 thread(s)

Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 33554432 (32.0MB)
NewSize = 11010048 (10.5MB)
MaxNewSize = 11010048 (10.5MB)
OldSize = 22544384 (21.5MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
capacity = 4718592 (4.5MB)
used = 4718592 (4.5MB)
free = 0 (0.0MB)
100.0% used
From Space:
capacity = 3145728 (3.0MB)
used = 0 (0.0MB)
free = 3145728 (3.0MB)
0.0% used
To Space:
capacity = 3145728 (3.0MB)
used = 0 (0.0MB)
free = 3145728 (3.0MB)
0.0% used
PS Old Generation
capacity = 22544384 (21.5MB)
used = 22106680 (21.08257293701172MB)
free = 437704 (0.41742706298828125MB)
98.0584787767987% used

13365 interned Strings occupying 1920632 bytes.

根据上面我们导出的内存映像文件,我们这时候下载一个mat软件,然后在此软件内打开我们的内存映像文件
点我去下载MAT软件
MAT软件加载内存映像文件
MAT分析

下一篇继续学习jvm调优的其他方式

------本文结束感谢阅读------
🐶 您的支持将鼓励我继续创作 🐶