IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

Java 6 JVM参数选项大全(中文版)

淘宝JAVA中间件团队博客 2011-06-23 13:34:17 累计浏览 5,120 次
本机暂存

   本文是基于最新的SUN官方文档Java SE 6 Hotspot VM Options 编写的译文。主要介绍JVM中的非稳态选项及其使用说明。

   为了让读者明白每个选项的含义,作者在原文基础上补充了大量的资料。希望这份文档,对正在研究JVM参数的朋友有帮助!

   另外,考虑到本文档是初稿,如有描述错误,敬请指正。

   非稳态选项使用说明

   -XX:+

   -XX:-

   -XX:

    -XX:

   行为选项

选项默认值与限制描述
-XX:-AllowUserSignalHandlers限于Linux和Solaris,默认不启用允许为java进程安装信号处理器。

    Java信号处理相关知识,详见 http://kenwublog.com/java-asynchronous-notify-based-on-signal

-XX:-DisableExplicitGC默认不启用禁止在运行期显式地调用 System.gc()。

   开启该选项后,GC的触发时机将由Garbage Collector全权掌控。

    注意:你熟悉的代码里没调用System.gc(),不代表你依赖的框架工具没在使用。

   例如RMI就在多数用户毫不知情的情况下,显示地调用GC来防止自身OOM。

   请仔细权衡禁用带来的影响。

-XX:-RelaxAccessControlCheck默认不启用在Class校验器中,放松对访问控制的检查。

   作用与reflection里的setAccessible类似。

-XX:-UseConcMarkSweepGC默认不启用启用CMS低停顿垃圾收集器。

   资料详见:http://kenwublog.com/docs/CMS_GC.pdf

-XX:-UseParallelGC-server时启用

   其他情况下,默认不启用

策略为新生代使用并行清除,年老代使用单线程Mark-Sweep-Compact的垃圾收集器。
-XX:-UseParallelOldGC默认不启用策略为老年代和新生代都使用并行清除的垃圾收集器。
-XX:-UseSerialGC-client时启用

   其他情况下,默认不启用

使用串行垃圾收集器。
-XX:+UseSplitVerifierjava5默认不启用

   java6默认启用

使用新的Class类型校验器 。

    新Class类型校验器有什么特点?

    新Class类型校验器,将老的校验步骤拆分成了两步:

    1,类型推断。

    2,类型校验。

   新类型校验器通过在javac编译时嵌入类型信息到bytecode中,省略了类型推断这一步,从而提升了classloader的性能。

   Classload顺序(供参考)

    load -> verify -> prepare -> resove -> init

    关联选项:

    -XX:+FailOverToOldVerifier

-XX:+FailOverToOldVerifierJava6新引入选项,默认启用如果新的Class校验器检查失败,则使用老的校验器。

   为什么会失败?

   因为JDK6最高向下兼容到JDK1.2,而JDK1.2的class info 与JDK6的info存在较大的差异,所以新校验器可能会出现校验失败的情况。

    关联选项:

    -XX:+UseSplitVerifier

-XX:+HandlePromotionFailurejava5以前是默认不启用,java6默认启用关闭新生代收集担保。

    什么是新生代收集担保?

    在一次理想化的minor gc中,Eden和First Survivor中的活跃对象会被复制到Second Survivor。

    然而,Second Survivor不一定能容纳下所有从E和F区copy过来的活跃对象。

   为了确保minor gc能够顺利完成,GC需要在年老代中额外保留一块足以容纳所有活跃对象的内存空间。

    这个预留操作,就被称之为新生代收集担保(New Generation Guarantee)。如果预留操作无法完成时,仍会触发major gc(full gc)。

   为什么要关闭新生代收集担保?

    因为在年老代中预留的空间大小,是无法精确计算的。

   为了确保极端情况的发生,GC参考了最坏情况下的新生代内存占用,即Eden+First Survivor。

   这种策略无疑是在浪费年老代内存,从时序角度看,还会提前触发Full GC。

   为了避免如上情况的发生,JVM允许开发者手动关闭新生代收集担保。

   在开启本选项后,minor gc将不再提供新生代收集担保,而是在出现survior或年老代不够用时,抛出promotion failed异常。

-XX:+UseSpinningjava1.4.2和1.5需要手动启用, java6默认已启用启用多线程自旋锁优化。

    自旋锁优化原理

   大家知道,Java的多线程安全是基于Lock机制实现的,而Lock的性能往往不如人意。

    原因是,monitorenter与monitorexit这两个控制多线程同步的bytecode原语,是JVM依赖操作系统互斥(mutex)来实现的。

    互斥是一种会导致线程挂起,并在较短的时间内又必须重新调度回原线程的,较为消耗资源的操作。

   为了避免进入OS互斥,Java6的开发者们提出了自旋锁优化。

   自旋锁优化的原理是在线程进入OS互斥前,通过CAS自旋一定的次数来检测锁的释放。

   如果在自旋次数未达到预设值前锁已被释放,则当前线程会立即持有该锁。

   CAS检测锁的原理详见: http://kenwublog.com/theory-of-lightweight-locking-upon-cas

    关联选项:

    -XX:PreBlockSpin=10

-XX:PreBlockSpin=10-XX:+UseSpinning 必须先启用,对于java6来说已经默认启用了,这里默认自旋10次控制多线程自旋锁优化的自旋次数。(什么是自旋锁优化?见 -XX:+UseSpinning 处的描述)

    关联选项:

    -XX:+UseSpinning

-XX:+ScavengeBeforeFullGC默认启用在Full GC前触发一次Minor GC。
-XX:+UseGCOverheadLimit默认启用限制GC的运行时间。如果GC耗时过长,就抛OOM。
-XX:+UseTLAB1.4.2以前和使用-client选项时,默认不启用,其余版本默认启用启用线程本地缓存区(Thread Local)。
-XX:+UseThreadPriorities默认启用使用本地线程的优先级。
-XX:+UseAltSigs限于Solaris,默认启用为了防止与其他发送信号的应用程序冲突,允许使用候补信号替代 SIGUSR1和SIGUSR2。
-XX:+UseBoundThreads限于Solaris, 默认启用绑定所有的用户线程到内核线程。

    减少线程进入饥饿状态(得不到任何cpu time)的次数。

-XX:+UseLWPSynchronization限于solaris,默认启用使用轻量级进程(内核线程)替换线程同步。
-XX:+MaxFDLimit限于Solaris,默认启用设置java进程可用文件描述符为操作系统允许的最大值。
-XX:+UseVMInterruptibleIO限于solaris,默认启用在solaris中,允许运行时中断线程 。

性能选项

选项与默认值默认值与限制描述
-XX:+AggressiveOptsJDK 5 update 6后引入,但需要手动启用。

   JDK6默认启用。

启用JVM开发团队最新的调优成果。例如编译优化,偏向锁,并行年老代收集等。
-XX:CompileThreshold=100001000通过JIT编译器,将方法编译成机器码的触发阀值,可以理解为调用方法的次数,例如调1000次,将方法编译为机器码。
-XX:LargePageSizeInBytes=4m默认4m

   amd64位:2m

设置堆内存的内存页大小。

   调整内存页的方法和性能提升原理,详见 http://kenwublog.com/tune-large-page-for-jvm-optimization

-XX:MaxHeapFreeRatio=7070GC后,如果发现空闲堆内存占到整个预估上限值的70%,则收缩预估上限值。

   什么是预估上限值?

   JVM在启动时,会申请最大值(-Xmx指定的数值)的地址空间,但其中绝大部分空间不会被立即分配(virtual)。

   它们会一直保留着,直到运行过程中,JVM发现实际占用接近已分配上限值时,才从virtual里再分配掉一部分内存。

   这里提到的已分配上限值,也可以叫做预估上限值。

    引入预估上限值的好处是,可以有效地控制堆的大小。堆越小,GC效率越高嘛。

   注意:预估上限值的大小一定小于或等于最大值。

-XX:MaxNewSize=size1.3.1 Sparc: 32m

   1.3.1 x86: 2.5m

新生代占整个堆内存的最大值。
-XX:MaxPermSize=64m5.0以后: 64 bit VMs会增大预设值的30%

   1.4 amd64: 96m

   1.3.1 -client: 32m

   其他默认 64m

Perm(俗称方法区)占整个堆内存的最大值。
-XX:MinHeapFreeRatio=4040GC后,如果发现空闲堆内存占到整个预估上限值的40%,则增大上限值。

   (什么是预估上限值?见 -XX:MaxHeapFreeRatio 处的描述)

   关联选项:

   -XX:MaxHeapFreeRatio=70

-XX:NewRatio=2Sparc -client: 8

   x86 -server: 8

   x86 -client: 12

   -client: 4 (1.3)

   8 (1.3.1+)

   x86: 12

   其他默认 2

新生代和年老代的堆内存占用比例。

   例如2例如2表示新生代占年老代的1/2,占整个堆内存的1/3。

-XX:NewSize=2.125m5.0以后: 64 bit Vms会增大预设值的30%

   x86: 1m

   x86, 5.0以后: 640k

   其他默认 2.125m

新生代预估上限的默认值。(什么是预估上限值?见 -XX:MaxHeapFreeRatio 处的描述)
-XX:ReservedCodeCacheSize=32mSolaris 64-bit, amd64, -server x86: 48m

   1.5.0_06之前, Solaris 64-bit amd64: 1024m

   其他默认 32m

设置代码缓存的最大值,编译时用。
-XX:SurvivorRatio=8Solaris amd64: 6

   Sparc in 1.3.1: 25

   Solaris platforms5.0以前: 32

   其他默认 8

Eden与Survivor的占用比例。例如8表示,一个survivor区占用 1/8 的Eden内存,即1/10的新生代内存,为什么不是1/9?

   因为我们的新生代有2个survivor,即S1和S22。所以survivor总共是占用新生代内存的 2/10,Eden与新生代的占比则为 8/10。

-XX:TargetSurvivorRatio=5050实际使用的survivor空间大小占比。默认是50%,最高90%。
-XX:ThreadStackSize=512Sparc: 512

   Solaris x86: 320(5.0以前 256)

   Sparc 64 bit: 1024

   Linux amd64: 1024 (5.0 以前 0)

   其他默认 512.

线程堆栈大小
-XX:+UseBiasedLockingJDK 5 update 6后引入,但需要手动启用。

   JDK6默认启用。

启用偏向锁。

   偏向锁原理详见 http://kenwublog.com/theory-of-java-biased-locking

-XX:+UseFastAccessorMethods默认启用优化原始类型的getter方法性能。
-XX:-UseISM默认启用启用solaris的ISM。

   详见Intimate Shared Memory.

-XX:+UseLargePagesJDK 5 update 5后引入,但需要手动启用。

   JDK6默认启用。

启用大内存分页。

   调整内存页的方法和性能提升原理,详见http://kenwublog.com/tune-large-page-for-jvm-optimization

   关联选项

   -XX:LargePageSizeInBytes=4m

-XX:+UseMPSS1.4.1 之前: 不启用

   其余版本默认启用

启用solaris的MPSS,不能与ISM同时使用。
-XX:+StringCache默认启用启用字符串缓存。
-XX:AllocatePrefetchLines=11与机器码指令预读相关的一个选项,资料比较少,本文档不做解释。有兴趣的朋友请自行阅读官方doc。
-XX:AllocatePrefetchStyle=11与机器码指令预读相关的一个选项,资料比较少,本文档不做解释。有兴趣的朋友请自行阅读官方doc。

调试选项

选项与默认值默认值与限制描述
-XX:-CITime1.4引入。

   默认启用

打印JIT编译器编译耗时。
-XX:ErrorFile=./hs_err_pid.logJava 6引入。如果JVM crashed,将错误日志输出到指定文件路径。
-XX:-ExtendedDTraceProbesJava6引入,限于solaris

   默认不启用

启用dtrace诊断。
-XX:HeapDumpPath=./java_pid.hprof默认是java进程启动位置,即user.dir堆内存快照的存储文件路径。

   什么是堆内存快照?

   当java进程因OOM或crash被OS强制终止后,会生成一个hprof(Heap PROFling)格式的堆内存快照文件。该文件用于线下调试,诊断,查找问题。

   文件名一般为

   java___

   解析快照文件,可以使用 jhat, eclipse MAT,gdb等工具。

-XX:-HeapDumpOnOutOfMemoryError1.4.2 update12 和 5.0 update 7 引入。

   默认不启用

在OOM时,输出一个dump.core文件,记录当时的堆内存快照(什么是堆内存快照? 见 -XX:HeapDumpPath 处的描述)。
-XX:OnError=”;1.4.2 update 9引入当java每抛出一个ERROR时,运行指定命令行指令集。指令集是与OS环境相关的,在linux下多数是bash脚本,windows下是dos批处理。
-XX:OnOutOfMemoryError=”;

   

1.4.2 update 12和java6时引入当第一次发生OOM时,运行指定命令行指令集。指令集是与OS环境相关的,在linux下多数是bash脚本,windows下是dos批处理。
-XX:-PrintClassHistogram默认不启用在Windows下, 按ctrl-break或Linux下是执行kill -3(发送SIGQUIT信号)时,打印class柱状图。

   Jmap

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. SmartSprites - 命令行形式的CSS Sprites生成器 (累计阅读 123,894)
  2. Java开发岗位面试题归类汇总 (累计阅读 22,155)
  3. android 开发入门 (累计阅读 19,527)
  4. 我的PHP,Python和Ruby之路 (累计阅读 13,146)
  5. HashMap解决hash冲突的方法 (累计阅读 12,652)
  6. 浅谈TCP优化 (累计阅读 11,082)
  7. 一个大二学生有关如何成为一名软件工程师的疑问及答复 (累计阅读 9,178)
  8. Java程序员应该知道的10个eclipse调试技巧 (累计阅读 8,012)
  9. 如何让员工忠于公司? (累计阅读 7,939)
  10. Java技术路线 (累计阅读 7,725)