本文将尝试阐释 JVM 参数 InitialRAMPercentage、MinRAMPercentage 以及 MaxRAMPercentage 之间的区别。这些参数在 Java 8 update 191 及之后版本中引入。如果您在物理服务器或容器中运行程序,那么这些参数可用于配置 Java 程序的堆内存大小。在本文中,我们将了解一下其中的差异。
InitialRAMPercentage
“-XX:InitialRAMPercentage”用于计算 Java 应用程序的初始堆内存大小。假设您配置 -XX:InitialRAMPercentage=25,且整体物理内存(或容器内存)配置为 1GB,那么 Java 程序的堆内存大小将为 250MB 左右(即:1GB 的 25%)。
“-XX:InitialRAMPercentage”仅会在没有传递“-Xms” JVM 参数时用于确定初始堆内存大小。如果传递了“-Xms” JVM 参数,那么 JVM 会忽视“-XX:InitialRAMPercentage”。
MaxRAMPercentage、MinRAMPercentage
需同时使用“-XX:MaxRAMPercentage”与“-XX:MinRAMPercentage”才能确认最大 Java 堆内存大小。JDK 研发团队其实应该给“-XX:MinRAMPercentage”取一个更好的名字。现在的名字“-XX:MinRAMPercentage”可能会让我们觉得这个参数是用来配置最小堆内存大小的。但实际上却并不是这样。
“-XX:MinRAMPercentage” JVM 参数仅在物理服务器(或容器)的总可用内存小于大约 250MB 时才会被用于计算 Java 堆内存的大小。假设您配置了 -XX:MinRAMPercentage=50 并且整体物理(或容器)内存为 100MB,那么 Java 程序的最大堆内存大小将被设置为 50MB(即 100MB 的 50%)。
“-XX:MaxRAMPercentage” JVM 参数仅在物理服务器(或容器)的总可用内存大于大约 250MB 时才会被用于计算 Java 堆内存的大小。假设您配置了 -XX:MaxRAMPercentage=75 并且整体物理服务器(或容器)内存为 1GB,那么 Java 程序的最大堆内存大小将被设置为 750MB(即 1GB 的 75%)。
为了证明这一理论,我们来看看下面的两个例子。
示例 1:小内存
让我们将容器的内存大小配置为 100MB,MaxRAMPercentage 配置为 25,MinRAMPercentage 配置为 50。由于容器内存为 100MB(小于 250MB 的限制),所以 JVM 会根据“MinRAMPercentage”来计算堆内存的大小。您应该能注意到,JVM 报告该配置的最大堆内存大小为 48.38MB(即:100MB 的 50%)。“MaxRAMPercentage” JVM 参数将被忽视。
# docker run -m 100MB openjdk:10 java -XX:MaxRAMPercentage=25 -XX:MinRAMPercentage=50 -XshowSettings:vm -version
VM settings:
Max.Heap Size (Estimated): 48.38M
Using VM: OpenJDK 64-Bit Server VM
示例 2:大内存
让我们将容器的内存大小配置为 1GB,MaxRAMPercentage 配置为 25,MinRAMPercentage 配置为 50。由于容器内存为 1GB(大于 250MB 的限制),所以 JVM 会根据“MaxRAMPercentage”来计算堆内存的大小。您应该能注意到,JVM 报告该配置的最大堆内存大小为 247.50MB(即:1GB 的 25%)。“MinRAMPercentage” JVM 参数将被忽视。
# docker run -m 1GB openjdk:10 java -XX:MaxRAMPercentage=25 -XX:MinRAMPercentage=50 -XshowSettings:vm -version
VM settings:
Max.Heap Size (Estimated): 247.50M
Using VM: OpenJDK 64-Bit Server VM
“-XX:MaxRAMPercentage”和“XX:MinRAMPercentage”仅会在没有传递“-Xms” JVM 参数时用于确定最大堆内存大小。如果传递了“-Xmx” JVM 参数,那么 JVM 将忽视上面的两个参数。
在下面的示例中,您可以看到我们配置了 “-XX:MaxRAMPercentage=25”、“-XX:MinRAMPercentage=25”和“-Xmx512m”。其中最大堆内存大小被设置为了 512MB,这意味着指定的“-Xmx”值已生效。
# docker run -m 1GB openjdk:10 java -XX:MaxRAMPercentage=25 -XX:MinRAMPercentage=25 -Xmx512m -XshowSettings:vm -version
VM settings:
Max.Heap Size: 512.00M
Using VM: OpenJDK 64-Bit Server VM
Best Practice: When you are starting to use ‘-XX:MaxRAMPercentage’, ‘-XX:MinRAMPercentage’, ‘-Xmx512m’ JVM arguments it has potential to impact your garbage collection, performance characteristics of your application. You can use free tools like GCeasy, IBM GC & Memory Visualizer, HP jmeter to study this behavior.
结论
简而言之:
a.如需为程序设置初始堆内存大小,请使用“-XX:InitialRAMPercentage”
b. 如果配置了“-Xms”,则在确定初始堆内存大小时“-XX:InitialRAMPercentage”不会生效。
c.“-XX:MinRAMPercentage”和“-XX:MaxRAMPercentage”两者都可用于设置程序的最大堆内存大小。
d. 如果配置了“-Xms”,则在确定最大堆内存大小时“-XX:MinRAMPercentage”和“-XX:MaxRAMPercentage”不会生效。
e.如果您的物理服务器(或容器)的总内存大小超过 250MB,那么就不必配置“-XX:MinRAMPercentage”,只配置“-XX:MaxRAMPercentage”就足够了。大多数企业级 Java 程序的运行内存会超过 250MB(除非您在使用 Java 构建 IoT 或网络设备程序)。
Leave a Reply