1
1
---
2
+ title : 最重要的 JVM 参数总结
2
3
category : Java
3
4
tag :
4
5
- JVM
5
6
---
6
7
7
-
8
- # 最重要的 JVM 参数总结
9
-
10
- 本文由 JavaGuide 翻译自 [ https://www.baeldung.com/jvm-parameters ] ( https://www.baeldung.com/jvm-parameters ) ,并对文章进行了大量的完善补充。翻译不易,如需转载请注明出处,作者:[ baeldung] ( https://www.baeldung.com/author/baeldung/ ) 。
8
+ > 本文由 JavaGuide 翻译自 [ https://www.baeldung.com/jvm-parameters ] ( https://www.baeldung.com/jvm-parameters ) ,并对文章进行了大量的完善补充。
9
+ >
10
+ > JDK 版本:1.8
11
11
12
12
## 1.概述
13
13
14
- 在本篇文章中,你将掌握最常用的 JVM 参数配置。如果对于下面提到了一些概念比如堆、
14
+ 在本篇文章中,你将掌握最常用的 JVM 参数配置。
15
15
16
16
## 2.堆内存相关
17
17
18
- > Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建。** 此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。**
18
+ > Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建。** 此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。**
19
19
20
20
### 2.1.显式指定堆内存` –Xms ` 和` -Xmx `
21
21
22
22
与性能有关的最常见实践之一是根据应用程序要求初始化堆内存。如果我们需要指定最小和最大堆大小(推荐显示指定大小),以下参数可以帮助你实现:
23
23
24
- ```
25
- -Xms<heap size>[unit]
24
+ ``` bash
25
+ -Xms< heap size> [unit]
26
26
-Xmx< heap size> [unit]
27
27
```
28
28
29
29
- ** heap size** 表示要初始化内存的具体大小。
30
- - ** unit** 表示要初始化内存的单位。单位为*** “ g”*** (GB) 、*** “ m”*** (MB)、*** “ k”* ** (KB)。
30
+ - ** unit** 表示要初始化内存的单位。单位为** _ “ g”_ ** (GB) 、** _ “ m”_ ** (MB)、** _ “ k”_ ** (KB)。
31
31
32
- 举个栗子🌰,如果我们要为JVM分配最小2 GB和最大5 GB的堆内存大小 ,我们的参数应该这样来写:
32
+ 举个栗子 🌰,如果我们要为 JVM 分配最小 2 GB 和最大 5 GB 的堆内存大小 ,我们的参数应该这样来写:
33
33
34
- ```
34
+ ``` bash
35
35
-Xms2G -Xmx5G
36
36
```
37
37
38
38
### 2.2.显式新生代内存(Young Generation)
39
39
40
- 根据[ Oracle官方文档 ] ( https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/sizing.html ) ,在堆总可用内存配置完成之后,第二大影响因素是为 ` Young Generation ` 在堆内存所占的比例。默认情况下,YG 的最小大小为 1310 * MB * ,最大大小为* 无限制* 。
40
+ 根据[ Oracle 官方文档 ] ( https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/sizing.html ) ,在堆总可用内存配置完成之后,第二大影响因素是为 ` Young Generation ` 在堆内存所占的比例。默认情况下,YG 的最小大小为 1310 _ MB _ ,最大大小为* 无限制* 。
41
41
42
42
一共有两种指定 新生代内存(Young Ceneration)大小的方法:
43
43
44
44
** 1.通过` -XX:NewSize ` 和` -XX:MaxNewSize ` 指定**
45
45
46
- ```
47
- -XX:NewSize=<young size>[unit]
46
+ ``` bash
47
+ -XX:NewSize=< young size> [unit]
48
48
-XX:MaxNewSize=< young size> [unit]
49
49
```
50
50
51
- 举个栗子🌰,如果我们要为 新生代分配 最小256m 的内存,最大 1024m的内存我们的参数应该这样来写 :
51
+ 举个栗子 🌰,如果我们要为 新生代分配 最小 256m 的内存,最大 1024m 的内存我们的参数应该这样来写 :
52
52
53
- ```
53
+ ``` bash
54
54
-XX:NewSize=256m
55
55
-XX:MaxNewSize=1024m
56
56
```
57
57
58
- ** 2.通过` -Xmn<young size>[unit] ` 指定**
58
+ ** 2.通过` -Xmn<young size>[unit] ` 指定**
59
59
60
- 举个栗子🌰,如果我们要为 新生代分配256m的内存(NewSize与MaxNewSize设为一致 ),我们的参数应该这样来写:
60
+ 举个栗子 🌰,如果我们要为 新生代分配 256m 的内存(NewSize 与 MaxNewSize 设为一致 ),我们的参数应该这样来写:
61
61
62
- ```
63
- -Xmn256m
62
+ ``` bash
63
+ -Xmn256m
64
64
```
65
65
66
66
GC 调优策略中很重要的一条经验总结是这样说的:
@@ -69,21 +69,21 @@ GC 调优策略中很重要的一条经验总结是这样说的:
69
69
70
70
另外,你还可以通过 ** ` -XX:NewRatio=<int> ` ** 来设置老年代与新生代内存的比值。
71
71
72
- 比如下面的参数就是设置老年代与新生代内存的比值为1。也就是说老年代和新生代所占比值为1 :1,新生代占整个堆栈的 1/2。
72
+ 比如下面的参数就是设置老年代与新生代内存的比值为 1。也就是说老年代和新生代所占比值为 1 :1,新生代占整个堆栈的 1/2。
73
73
74
74
```
75
75
-XX:NewRatio=1
76
76
```
77
77
78
78
### 2.3.显式指定永久代/元空间的大小
79
79
80
- ** 从Java 8开始 ,如果我们没有指定 Metaspace 的大小,随着更多类的创建,虚拟机会耗尽所有可用的系统内存(永久代并不会出现这种情况)。**
80
+ ** 从 Java 8 开始 ,如果我们没有指定 Metaspace 的大小,随着更多类的创建,虚拟机会耗尽所有可用的系统内存(永久代并不会出现这种情况)。**
81
81
82
82
JDK 1.8 之前永久代还没被彻底移除的时候通常通过下面这些参数来调节方法区大小
83
83
84
- ``` java
85
- - XX : PermSize = N // 方法区 (永久代) 初始大小
86
- - XX : MaxPermSize = N // 方法区 (永久代) 最大大小,超过这个值将会抛出 OutOfMemoryError 异常:java.lang.OutOfMemoryError: PermGen
84
+ ``` bash
85
+ -XX:PermSize=N # 方法区 (永久代) 初始大小
86
+ -XX:MaxPermSize=N # 方法区 (永久代) 最大大小,超过这个值将会抛出 OutOfMemoryError 异常:java.lang.OutOfMemoryError: PermGen
87
87
```
88
88
89
89
相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入方法区后就“永久存在”了。
@@ -92,9 +92,9 @@ JDK 1.8 之前永久代还没被彻底移除的时候通常通过下面这些参
92
92
93
93
下面是一些常用参数:
94
94
95
- ``` java
96
- - XX : MetaspaceSize = N // 设置 Metaspace 的初始(和最小大小)
97
- - XX : MaxMetaspaceSize = N // 设置 Metaspace 的最大大小,如果不指定大小的话,随着更多类的创建,虚拟机会耗尽所有可用的系统内存。
95
+ ``` bash
96
+ -XX:MetaspaceSize=N # 设置 Metaspace 的初始(和最小大小)
97
+ -XX:MaxMetaspaceSize=N # 设置 Metaspace 的最大大小,如果不指定大小的话,随着更多类的创建,虚拟机会耗尽所有可用的系统内存。
98
98
```
99
99
100
100
## 3.垃圾收集相关
@@ -103,16 +103,16 @@ JDK 1.8 之前永久代还没被彻底移除的时候通常通过下面这些参
103
103
104
104
为了提高应用程序的稳定性,选择正确的[ 垃圾收集] ( http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html ) 算法至关重要。
105
105
106
- JVM具有四种类型的 * GC * 实现:
106
+ JVM 具有四种类型的 GC 实现:
107
107
108
108
- 串行垃圾收集器
109
109
- 并行垃圾收集器
110
- - CMS垃圾收集器
111
- - G1垃圾收集器
110
+ - CMS 垃圾收集器
111
+ - G1 垃圾收集器
112
112
113
113
可以使用以下参数声明这些实现:
114
114
115
- ```
115
+ ``` bash
116
116
-XX:+UseSerialGC
117
117
-XX:+UseParallelGC
118
118
-XX:+UseParNewGC
@@ -121,24 +121,80 @@ JVM具有四种类型的*GC*实现:
121
121
122
122
有关* 垃圾回收* 实施的更多详细信息,请参见[ 此处] ( https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/jvm/JVM%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6.md ) 。
123
123
124
- ### 3.2.GC记录
125
-
126
- 为了严格监控应用程序的运行状况,我们应该始终检查JVM的* 垃圾回收* 性能。最简单的方法是以人类可读的格式记录* GC* 活动。
127
-
128
- 使用以下参数,我们可以记录* GC* 活动:
129
-
130
- ```
131
- -XX:+UseGCLogFileRotation
132
- -XX:NumberOfGCLogFiles=< number of log files >
133
- -XX:GCLogFileSize=< file size >[ unit ]
134
- -Xloggc:/path/to/gc.log
135
- ```
136
-
137
- ## 推荐阅读
138
-
139
- - [ CMS GC 默认新生代是多大?] ( https://www.jianshu.com/p/832fc4d4cb53 )
140
- - [ CMS GC启动参数优化配置] ( https://www.cnblogs.com/hongdada/p/10277782.html )
141
- - [ 从实际案例聊聊Java应用的GC优化-美团技术团队] ( https://tech.meituan.com/2017/12/29/jvm-optimize.html )
142
- - [ JVM性能调优详解] ( https://www.choupangxia.com/2019/11/11/interview-jvm-gc-08/ ) (2019-11-11)
143
- - [ JVM参数使用手册] ( https://segmentfault.com/a/1190000010603813 )
144
- -
124
+ ### 3.2.GC 日志记录
125
+
126
+ 生产环境上,或者其他要测试 GC 问题的环境上,一定会配置上打印 GC 日志的参数,便于分析 GC 相关的问题。
127
+
128
+ ``` bash
129
+ # 必选
130
+ # 打印基本 GC 信息
131
+ -XX:+PrintGCDetails
132
+ -XX:+PrintGCDateStamps
133
+ # 打印对象分布
134
+ -XX:+PrintTenuringDistribution
135
+ # 打印堆数据
136
+ -XX:+PrintHeapAtGC
137
+ # 打印Reference处理信息
138
+ # 强引用/弱引用/软引用/虚引用/finalize 相关的方法
139
+ -XX:+PrintReferenceGC
140
+ # 打印STW时间
141
+ -XX:+PrintGCApplicationStoppedTime
142
+
143
+ # 可选
144
+ # 打印safepoint信息,进入 STW 阶段之前,需要要找到一个合适的 safepoint
145
+ -XX:+PrintSafepointStatistics
146
+ -XX:PrintSafepointStatisticsCount=1
147
+
148
+ # GC日志输出的文件路径
149
+ -Xloggc:/path/to/gc-%t.log
150
+ # 开启日志文件分割
151
+ -XX:+UseGCLogFileRotation
152
+ # 最多分割几个文件,超过之后从头文件开始写
153
+ -XX:NumberOfGCLogFiles=14
154
+ # 每个文件上限大小,超过就触发分割
155
+ -XX:GCLogFileSize=50M
156
+ ```
157
+
158
+ ## 4.处理 OOM
159
+
160
+ 对于大型应用程序来说,面对内存不足错误是非常常见的,这反过来会导致应用程序崩溃。这是一个非常关键的场景,很难通过复制来解决这个问题。
161
+
162
+ 这就是为什么 JVM 提供了一些参数,这些参数将堆内存转储到一个物理文件中,以后可以用来查找泄漏:
163
+
164
+ ``` bash
165
+ -XX:+HeapDumpOnOutOfMemoryError
166
+ -XX:HeapDumpPath=./java_pid< pid> .hprof
167
+ -XX:OnOutOfMemoryError=" < cmd args >;< cmd args >"
168
+ -XX:+UseGCOverheadLimit
169
+ ```
170
+
171
+ 这里有几点需要注意:
172
+
173
+ - ** HeapDumpOnOutOfMemoryError** 指示 JVM 在遇到 ** OutOfMemoryError** 错误时将 heap 转储到物理文件中。
174
+ - ** HeapDumpPath** 表示要写入文件的路径; 可以给出任何文件名; 但是,如果 JVM 在名称中找到一个 ` <pid> ` 标记,则当前进程的进程 id 将附加到文件名中,并使用` .hprof ` 格式
175
+ - ** OnOutOfMemoryError** 用于发出紧急命令,以便在内存不足的情况下执行; 应该在 ` cmd args ` 空间中使用适当的命令。例如,如果我们想在内存不足时重启服务器,我们可以设置参数: ` -XX:OnOutOfMemoryError="shutdown -r" ` 。
176
+ - ** UseGCOverheadLimit** 是一种策略,它限制在抛出 OutOfMemory 错误之前在 GC 中花费的 VM 时间的比例
177
+
178
+ ## 5.其他
179
+
180
+ - ` -server ` : 启用“ Server Hotspot VM”; 此参数默认用于 64 位 JVM
181
+ - ` -XX:+UseStringDeduplication ` : _ Java 8u20_ 引入了这个 JVM 参数,通过创建太多相同 String 的实例来减少不必要的内存使用; 这通过将重复 String 值减少为单个全局 ` char [] ` 数组来优化堆内存。
182
+ - ` -XX:+UseLWPSynchronization ` : 设置基于 LWP (轻量级进程)的同步策略,而不是基于线程的同步。
183
+ - ``-XX: LargePageSizeInBytes `: 设置用于 Java 堆的较大页面大小; 它采用 GB/MB/KB 的参数; 页面大小越大,我们可以更好地利用虚拟内存硬件资源; 然而,这可能会导致 PermGen 的空间大小更大,这反过来又会迫使 Java 堆空间的大小减小。
184
+ - ` -XX:MaxHeapFreeRatio ` : 设置 GC 后, 堆空闲的最大百分比,以避免收缩。
185
+ - ` -XX:SurvivorRatio ` : eden/survivor 空间的比例, 例如` -XX:SurvivorRatio=6 ` 设置每个 survivor 和 eden 之间的比例为 1:6。
186
+ - ` -XX:+UseLargePages ` : 如果系统支持,则使用大页面内存; 请注意,如果使用这个 JVM 参数,OpenJDK 7 可能会崩溃。
187
+ - ` -XX:+UseStringCache ` : 启用 String 池中可用的常用分配字符串的缓存。
188
+ - ` -XX:+UseCompressedStrings ` : 对 String 对象使用 ` byte [] ` 类型,该类型可以用纯 ASCII 格式表示。
189
+ - ` -XX:+OptimizeStringConcat ` : 它尽可能优化字符串串联操作。
190
+
191
+ ## 文章推荐
192
+
193
+ 这里推荐了非常多优质的 JVM 实践相关的文章,推荐阅读,尤其是 JVM 性能优化和问题排查相关的文章。
194
+
195
+ - [ 求你了,GC 日志打印别再瞎配置了 - 思否 - 2022] ( https://segmentfault.com/a/1190000039806436 )
196
+ - [ 一次大量 JVM Native 内存泄露的排查分析(64M 问题) - 掘金 - 2022] ( https://juejin.cn/post/7078624931826794503 )
197
+ - [ 听说 JVM 性能优化很难?今天我小试了一把! - 陈树义 - 2021] ( https://shuyi.tech/archives/have-a-try-in-jvm-combat )
198
+ - [ 你们要的线上 GC 问题案例来啦 - 编了个程 - 2021] ( https://mp.weixin.qq.com/s/df1uxHWUXzhErxW1sZ6OvQ )
199
+ - [ Java 中 9 种常见的 CMS GC 问题分析与解决 - 美团技术团队 - 2020] ( https://tech.meituan.com/2020/11/12/java-9-cms-gc.html )
200
+ - [ 从实际案例聊聊 Java 应用的 GC 优化-美团技术团队 - 美团技术团队 - 2017] ( https://tech.meituan.com/2017/12/29/jvm-optimize.html )
0 commit comments