堆内存相关
2.1.显式指定堆内存–Xms和-Xmx
-Xms<heap size>[unit]
-Xmx<heap size>[unit]- X: 特定于JVM实现的
- ms : memory size
- mx : maximum memory size
- heap size 表示要初始化内存的具体大小。
- unit 表示要初始化内存的单位。单位为 “ g” (GB)、“ m”(MB)、“ k”(KB)。
如
-Xms2G -Xmx5G2.2.显式新生代内存(Young Generation)
在堆总可用内存配置完成之后,第二大影响因素是为 Young Generation 在堆内存所占的比例。默认情况下,YG 的最小大小为 1310 MB,最大大小为 无限制。
一共有两种指定 新生代内存(Young Generation)大小的方法:
1.通过-XX:NewSize和-XX:MaxNewSize指定
-XX:NewSize=<young size>[unit]
-XX:MaxNewSize=<young size>[unit]2.通过-Xmn<young size>[unit]指定
GC 调优策略中很重要的一条经验总结是这样说的:
将新对象预留在新生代,由于 Full GC 的成本远高于 Minor GC,因此尽可能将对象分配在新生代是明智的做法,实际项目中根据 GC 日志分析新生代空间大小分配是否合理,适当通过“-Xmn”命令调节新生代大小,最大限度降低新对象直接进入老年代的情况。
另外,你还可以通过 -XX:NewRatio=<int> 来设置老年代与新生代内存的比值。
比如下面的参数就是设置老年代与新生代内存的比值为 1。也就是说老年代和新生代所占比值为 1:1,新生代占整个堆栈的 1/2。
-XX:NewRatio=12.3.显式指定永久代/元空间的大小
从 Java 8 开始,如果我们没有指定 Metaspace 的大小,随着更多类的创建,虚拟机会耗尽所有可用的系统内存(永久代并不会出现这种情况)。
下面是一些常用参数:
-XX:MetaspaceSize=N #设置 Metaspace 的full GC的阈值(通常两者设定相同的大小)
-XX:MaxMetaspaceSize=N #设置 Metaspace 的最大大小1、Metaspace 的初始容量并不是 -XX:MetaspaceSize 设置,无论 -XX:MetaspaceSize 配置什么值,对于 64 位 JVM 来说,Metaspace 的初始容量都是 21807104(约 20.8m)。
2、MetaspaceSize 表示 Metaspace 使用过程中触发 Full GC 的阈值,只对触发起作用。
3.垃圾收集相关
3.1.垃圾回收器
为了提高应用程序的稳定性,选择正确的垃圾收集算法至关重要。
JVM 具有四种类型的 GC 实现:
- 串行垃圾收集器
- 并行垃圾收集器
- CMS 垃圾收集器
- G1 垃圾收集器
可以使用以下参数声明这些实现:
-XX:+UseSerialGC
-XX:+UseParallelGC
-XX:+UseConcMarkSweepGC
-XX:+UseG1GC有关垃圾回收实施的更多详细信息,请参见此处。
3.2.GC 日志记录
生产环境上,或者其他要测试 GC 问题的环境上,一定会配置上打印 GC 日志的参数,便于分析 GC 相关的问题。
点击查看完整代码实现
点击查看完整代码实现
# 必选
# 打印基本 GC 信息
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
# 打印对象分布
-XX:+PrintTenuringDistribution
# 打印堆数据
-XX:+PrintHeapAtGC
# 打印Reference处理信息
# 强引用/弱引用/软引用/虚引用/finalize 相关的方法
-XX:+PrintReferenceGC
# 打印STW时间
-XX:+PrintGCApplicationStoppedTime
# 可选
# 打印safepoint信息,进入 STW 阶段之前,需要要找到一个合适的 safepoint
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1
# GC日志输出的文件路径
-Xloggc:/path/to/gc-%t.log
# 开启日志文件分割
-XX:+UseGCLogFileRotation
# 最多分割几个文件,超过之后从头文件开始写
-XX:NumberOfGCLogFiles=14
# 每个文件上限大小,超过就触发分割
-XX:GCLogFileSize=50M:::
4.处理 OOM
这就是为什么 JVM 提供了一些参数,这些参数将堆内存转储到一个物理文件中,以后可以用来查找泄漏:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./java_pid<pid>.hprof
-XX:OnOutOfMemoryError="< cmd args >;< cmd args >"
-XX:+UseGCOverheadLimit这里有几点需要注意:
- HeapDumpOnOutOfMemoryError 指示 JVM 在遇到 OutOfMemoryError 错误时将 heap 转储到物理文件中。
- HeapDumpPath 表示要写入文件的路径; 可以给出任何文件名; 但是,如果 JVM 在名称中找到一个
<pid>标记,则当前进程的进程 id 将附加到文件名中,并使用.hprof格式 - OnOutOfMemoryError 用于发出紧急命令,以便在内存不足的情况下执行; 应该在
cmd args空间中使用适当的命令。例如,如果我们想在内存不足时重启服务器,我们可以设置参数:-XX:OnOutOfMemoryError="shutdown -r"。 - UseGCOverheadLimit 是一种策略,它限制在抛出 OutOfMemory 错误之前在 GC 中花费的 VM 时间的比例
5.其他
-server: 启用“ Server Hotspot VM”; 此参数默认用于 64 位 JVM-XX:+UseStringDeduplication: Java 8u20 引入了这个 JVM 参数,通过创建太多相同 String 的实例来减少不必要的内存使用; 这通过将重复 String 值减少为单个全局char []数组来优化堆内存。-XX:+UseLWPSynchronization: 设置基于 LWP (轻量级进程)的同步策略,而不是基于线程的同步。-XX:LargePageSizeInBytes: 设置用于 Java 堆的较大页面大小; 它采用 GB/MB/KB 的参数; 页面大小越大,我们可以更好地利用虚拟内存硬件资源; 然而,这可能会导致 PermGen 的空间大小更大,这反过来又会迫使 Java 堆空间的大小减小。-XX:MaxHeapFreeRatio: 设置 GC 后, 堆空闲的最大百分比,以避免收缩。-XX:SurvivorRatio: eden/survivor 空间的比例, 例如-XX:SurvivorRatio=6设置每个 survivor 和 eden 之间的比例为 1:6。-XX:+UseLargePages: 如果系统支持,则使用大页面内存; 请注意,如果使用这个 JVM 参数,OpenJDK 7 可能会崩溃。-XX:+UseStringCache: 启用 String 池中可用的常用分配字符串的缓存。-XX:+UseCompressedStrings: 对 String 对象使用byte []类型,该类型可以用纯 ASCII 格式表示。-XX:+OptimizeStringConcat: 它尽可能优化字符串串联操作。
文章推荐
这里推荐了非常多优质的 JVM 实践相关的文章,推荐阅读,尤其是 JVM 性能优化和问题排查相关的文章。
- JVM 参数配置说明 - 阿里云官方文档 - 2022
- JVM 内存配置最佳实践 - 阿里云官方文档 - 2022
- 求你了,GC 日志打印别再瞎配置了 - 思否 - 2022
- 一次大量 JVM Native 内存泄露的排查分析(64M 问题) - 掘金 - 2022
- 一次线上 JVM 调优实践,FullGC40 次/天到 10 天一次的优化过程 - HeapDump - 2021
- 听说 JVM 性能优化很难?今天我小试了一把! - 陈树义 - 2021
- 你们要的线上 GC 问题案例来啦 - 编了个程 - 2021
- Java 中 9 种常见的 CMS GC 问题分析与解决 - 美团技术团队 - 2020
- 从实际案例聊聊 Java 应用的 GC 优化-美团技术团队 - 美团技术团队 - 2017
