Featured image of post JVM_04_JVM参数总结

JVM_04_JVM参数总结

🌏Java工程师 JVM 🎯 这篇文章用于记录 JVM_04_JVM参数总结 旨在掌握最常用的JVM参数配置

🎄堆内存相关

堆是Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。

内存区域常见配置参数

🍭关于命令行参数的 -XXX

在 Java 命令行参数中,以单个短横线 - 开头的参数是标准参数,它们被 JVM 直接识别和处理。这些参数的命名通常是简洁的,由一两个字符组成,后面可能跟着一个或多个参数值。

-X 前缀在 Java 命令行参数中通常表示这是一个非标准参数,或者说是一个高级选项,主要用于那些需要更深入配置 JVM 的用户。这些 -X 参数通常是由 JVM 实现者提供的,用于控制 JVM 的内部行为。

-Xms-Xmx 中的 msmx 并不是英文单词的缩写,而是参数值的指示符。在这里,ms 可以被理解为 “memory start”(内存起始),而 mx 可以被理解为 “memory maximum”(内存最大)。这种解释更多是基于参数作用的推测,而不是官方的命名规则。

在Java虚拟机(JVM)中,-XX 参数用于设置JVM的高级选项和性能调优参数。这些参数通常不是Java标准的一部分,而是由JVM实现(如HotSpot VM)提供的。因此,使用 -XX 参数时需要特别小心,因为错误的设置可能会影响JVM的稳定性和性能。

🍭显式指定堆内存 –Xms-Xmx

在Java虚拟机(JVM)中,-Xms-Xmx 是两个用于设置Java堆内存初始大小和最大大小的选项。它们是JVM启动参数的一部分,允许开发者和系统管理员调整Java应用程序的内存使用。

  • -Xms 代表初始Java堆大小(memory start) 这个选项用于设置JVM启动时Java堆内存的初始分配量。“memory start"的解释更多是基于参数作用的推测,而不是官方的命名规则。
  • -Xmx 代表最大Java堆大小(memory maximum) 这个选项用于限制JVM可以使用的最大Java堆内存量。“memory maximum"的解释更多是基于参数作用的推测,而不是官方的命名规则。

如果我们想要设置一个Java应用程序的初始堆大小为128MB,最大堆大小为1024MB,你可以在启动JVM时使用以下参数:

java -Xms128m -Xmx1024m -jar application.jar

这里,-Xms128m 设置了初始堆大小为128MB,而 -Xmx1024m 设置了最大堆大小为1024MB。这两个参数对于调整Java应用程序的性能和稳定性非常重要,特别是在处理大量数据或需要优化内存使用的情况下。

🍭显式指定新生代内存(Young Generation)

在堆总可用内存配置完成之后,第二大影响因素是为 Young Generation 在堆内存所占的比例。默认情况下,YG 的最小大小为 1310 MB,最大大小为无限制

一共有两种指定 新生代内存(Young Generation)大小的方法:

(1)通过-XX:NewSize-XX:MaxNewSize指定 如果我们要为新生代分配最小 256m 的内存,最大 1024m 的内存我们的参数应该这样来写:

-XX:NewSize=256m
-XX:MaxNewSize=1024m

(2)通过-Xmn<young size>[unit]指定 如果我们要为新生代分配 256m 的内存(NewSize 与 MaxNewSize 设为一致),我们的参数应该这样来写:

-Xmn256m

GC 调优策略中很重要的一条经验总结是这样说的:

将新对象预留在新生代,由于 Full GC 的成本远高于 Minor GC,因此尽可能将对象分配在新生代是明智的做法,实际项目中根据 GC 日志分析新生代空间大小分配是否合理,适当通过“-Xmn”命令调节新生代大小,最大限度降低新对象直接进入老年代的情况。

(3)通过 -XX:NewRatio=<int> 来设置老年代与新生代内存的比值

Eden区与Survivor区的大小通常并不是1:1的比例

-XX:NewRatio 的正确解释应该是这样的:如果 -XX:NewRatio=n,则老年代的大小将是新生代中一个Survivor区大小的 n 倍。这个设置会影响堆的总体布局和垃圾收集的性能。

常见的配置是Eden区比Survivor区大很多。例如,一个常见的默认配置是Eden:Survivor:Survivor = 8:1:1。在这个配置下,如果设置 -XX:NewRatio=1,老年代的大小将是新生代中一个Survivor区大小的1倍,而不是整个新生代大小的1/3。

-XX:NewRatio=1

🍭显式指定永久代/元空间的大小

JDK 1.8 的时候,方法区(HotSpot 的永久代)被彻底移除,取而代之是元空间,元空间使用的是本地内存。

下面是一些常用参数:

-XX:MetaspaceSize=N #设置 Metaspace 的初始大小(是一个常见的误区 无论 -XX:MetaspaceSize 配置什么值,对于 64 位 JVM 来说,Metaspace 的初始容量都是 21807104(约 20.8m))
-XX:MaxMetaspaceSize=N #设置 Metaspace 的最大大小

🎄垃圾收集相关

🍭 垃圾回收器相关

为了提高应用程序的稳定性,选择正确的垃圾收集算法至关重要。

JVM 具有四种类型的 GC 实现:

  • 串行垃圾收集器
  • 并行垃圾收集器
  • CMS 垃圾收集器
  • G1 垃圾收集器

可以使用以下参数声明这些实现:

-XX:+UseSerialGC
-XX:+UseParallelGC
-XX:+UseParNewGC
-XX:+UseG1GC

🍭 GC日志记录相关

生产环境上,或者其他要测试 GC 问题的环境上,一定会配置上打印 GC 日志的参数,便于分析 GC 相关的问题。

############################# 必选 #############################
# 打印基本 GC 信息
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
# 打印对象分布
-XX:+PrintTenuringDistribution
# 打印堆数据
-XX:+PrintHeapAtGC
# 打印Reference处理信息
# 强引用/弱引用/软引用/虚引用/finalize 相关的方法
-XX:+PrintReferenceGC
# 打印STW时间
-XX:+PrintGCApplicationStoppedTime

# GC日志输出的文件路径
-Xloggc:/path/to/gc-%t.log
# 开启日志文件分割
-XX:+UseGCLogFileRotation
# 最多分割几个文件,超过之后从头文件开始写
-XX:NumberOfGCLogFiles=14
# 每个文件上限大小,超过就触发分割
-XX:GCLogFileSize=50M

############################# 可选 #############################
# 打印safepoint信息,进入 STW 阶段之前,需要要找到一个合适的 safepoint
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1

🎄处理OOM(Out of Memery)

对于大型应用程序来说,面对内存不足错误是非常常见的,这反过来会导致应用程序崩溃。这是一个非常关键的场景,很难通过复制来解决这个问题。

这就是为什么 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 时间的比例

🎄其他JVM参数

-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 : 它尽可能优化字符串串联操作。

🎄原文链接

https://javaguide.cn/java/jvm/jvm-parameters-intro.html#_4-%E5%A4%84%E7%90%86-oom

Licensed under CC BY-NC-SA 4.0