JVM 参数调优(qbit)

前言

  • JVM 的参数有好几百个,听着有点吓人,好在最常用的参数只有两个,其他绝大多数参数都无需调整。可以参考廖雪峰的文章: JVM调优的正确姿势
-Xms8g 
-Xmx8g

Client/Server

  • JVM 有两种运行模式 Server 与 Client。
  • Client 模式启动速度较快,Server 模式启动较慢。
  • 启动进入稳定期长期运行之后 Server 模式的程序运行速度比 Client 要快很多。
  • 查看当前虚拟机处于哪种模式
λ java -version
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)
  • 64 位 JDK 无法切换到 Clinet 模式

打印 JVM 参数

  • 打印 JVM 参数初始值
λ java -XX:+PrintFlagsInitial
  • 打印 JVM 参数最终值
λ java -XX:+PrintFlagsFinal 2> nul
  • 打印被修改过的 JVM 参数
# 输出经由人工换行
λ java -XX:+PrintCommandLineFlags 2> nul
-XX:InitialHeapSize=266579392 
-XX:MaxHeapSize=4265270272 
-XX:+PrintCommandLineFlags 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:-UseLargePagesIndividualAllocation 
-XX:+UseParallelGC
  • 在 java 代码里面打印
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
private void printJvm() {
    MemoryMXBean memorymbean = ManagementFactory.getMemoryMXBean();
    System.out.println("堆内存信息: " + memorymbean.getHeapMemoryUsage());
    System.out.println("方法区内存信息: " + memorymbean.getNonHeapMemoryUsage());

    List inputArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
    System.out.println("\n####################运行时设置的JVM参数####################");
    System.out.println(inputArgs);

    System.out.println("\n####################运行时内存情况#######################");
    long totle = Runtime.getRuntime().totalMemory();
    System.out.println("总的内存量 [" + totle + "]");
    long free = Runtime.getRuntime().freeMemory();
    System.out.println("空闲的内存量 [" + free + "]");
    long max = Runtime.getRuntime().maxMemory();
    System.out.println("最大的内存量 [" + max + "]");
}

jvm 内存模型

  • 图片来源于网络

JVM 参数调优(qbit)_第1张图片

常用参数

-Xms: 初始堆大小
-Xmx: 最大堆大小
-XX:NewSize: 年轻代初始化内存的大小(注意:该值需要小于-Xms的值)
-XX:MaxnewSize: 年轻代可被分配的内存的最大上限(注意:该值需要小于-Xmx的值)
    从 JKD1.4 开始,MaxnewSize 是通过 NewRatio 计算出来的
-Xmn: 对-XX:newSize、-XX:MaxnewSize两个参数同时进行配置(JDK1.4之后才有该参数)
    官方推荐为对大小的 3/8,即 1/4 到 1/3 之间
-XX:NewRatio: 设置老年代和年轻代的比值
   若 -Xmn 已指定,则 OldSize = HeapSize - NewSize,无需再按比例计算。
   例如 NewRatio 为 3,表示 老年代/年轻代 = 3,年轻代占整个堆内存大小的 1/4
  • 对于年轻代的堆内存大小,默认情况下是通过 NewRatio(2) 计算出来的,即占用 1/3;在配置 Xmn 后,会覆盖默认的通过 NewRatio 计算出来的年轻代堆大小值
# 摘录的部分的输出行
# MaxHeapSize/MaxNewSize = 4265607168/1421869056 = 3
λ java -XX:+PrintFlagsFinal
    uintx NewRatio = 2                   {product}
    uintx MaxNewSize    := 1421869056    {product}
    uintx MaxHeapSize   := 4265607168    {product}
  • 一般 -Xms、-Xmx 两个参数会配置相同的值(优点:能够在Java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源)。

CompressedOops

压缩普通对象指针

compressed ordinary object pointers,压缩普通对象指针
(0, 2GB]      Compressed Oops mode: 32-bit
[2GB, 26GB]   Compressed Oops mode: Zero based,26G 不是确切值,视系统而定
(26GB, 32GB)  Compressed Oops mode: Non-zero disjoint base,32G 不是确切值,视系统而定
[32GB, )      CompressedOops 失效,32G 不是确切值,视系统而定

CompressedOops

检查 CompressedOops 阈值

  • 下面测试的粒度为 GB,也可以到 MB
  • 以下命令适用于 JDK7/JDK8
# 测试环境
Windows 10
JDK7
# CompressedOops 阈值
# 32 G,false 表示超过了阈值
> java -Xmx32g -XX:+PrintFlagsFinal 2> nul | findstr UseCompressedOops
     bool UseCompressedOops    = false    {lp64_product}
# 31G,true 表示在阈值之内
> java -Xmx31g -XX:+PrintFlagsFinal 2> nul | findstr UseCompressedOops
     bool UseCompressedOops    := true    {lp64_product}
# zero based Compressed Oops 阈值
# 32G,未启用压缩
> java -server -Xms32G -Xmx32G -XX:+UseConcMarkSweepGC -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode -version
java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)

# zero based Compressed Oops 阈值
# 30G,Non-zero
> java -server -Xms30G -Xmx30G -XX:+UseConcMarkSweepGC -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode -version
Protected page at the reserved heap base: 0x000000007fff0000 / 65536 bytes
heap address: 0x0000000080000000, size: 30802 MB, Compressed Oops with base: 0x000000007ffff000
java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)

# 30G,Zero based
> java -server -Xms29G -Xmx29G -XX:+UseConcMarkSweepGC -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode -version
heap address: 0x00000000bae00000, size: 29778 MB, zero based Compressed Oops
java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)

测试案例

这个案例中,分配 32g 比 31g 能创建的对象少了 50%
587889429/385481085 ≈ 1.525

JVM 参数调优(qbit)_第2张图片

这个案例中,48g 才基本达到 31g 的效果

JVM 参数调优(qbit)_第3张图片

本文出自 qbit snap

你可能感兴趣的:(内存管理,jvm调优,java)