附录 A 性能调优标志摘要

表A-1:调优JIT编译器的标志

标志 功能 使用场景 更多信息
-server 选择使用server编译器 适用于需长时间运行,同时又要求高性能的应用 “热点编译”,P59
-client 选择使用client编译器 适用于启动时间是最重要因素的应用 “热点编译”,P59
-XX:+TieredCompilation 使用tiered编译(同时选择client和server标志的特性) 适用于希望取得最佳性能,同时又有足够的内存可以支撑额外的编译代码的应用 “热点编译”,P59
-XX:ReservedCodeCacheSize= 设定JIT编译器进行代码编译的保留空间 当你遭遇警示消息“你的代码缓存已用尽”时,可以使用这个标志,通常结合Tiered编译标志一起使用 “调优代码缓存”,P67
-XX:InitialCodeCacheSize= 用于替JIT编译器编译代码分配初始空间 如果你需要为代码缓存预分配内存,可以使用该标志,不过这种情况不常发生 “调优代码缓存”,P67
-XX:CompileThreshold= 设置一段代码或循环执行多少次之后转而进行编译 使用server编译器时,调整这个标志可以让更多的方法变为编译执行,让编译更早地发生。如果你使用的不是Tiered编译,第一种情况有时就是一种优势。 “编译阈值”,P68
-XX:+PrintCompilation 在日志中输出JIT编译器进行的操作 如果你怀疑某个重要的方法没有进行编译,或者对编译器的工作流程感到好奇,都可以使用这个标志进行查看 “检测编译过程”,P70
-XX:+CICompilerCount= 设置JIT编译器使用的线程数 使用Tiered编译标志时,如果有太多的编译线程启动(尤其是在运行了多个JVM的大型机上),通过该标志可以调节JIT线程的数目 “编译线程”,P73

表A-2:选择GC算法的标志

标志 功能 使用场景 更多信息
-XX:+UseSerialGC 选择使用简单的单线程垃圾收集算法 适用于容量小于100 MB的堆 “Serial垃圾收集器”,P84
-XX:+UseParallelOldGC 应用线程停顿时使用多个线程对老年代进行垃圾回收 如果你的应用能够容忍偶尔发生的长时间停顿,而你又希望用最小的CPU消耗取得最大的吞吐量,可以考虑使用这个标志 “Throughput收集器”,P85
-XX:+UseParallelGC 应用线程停顿时使用多个线程对新生代空间进行垃圾收集 UseParallelGC标志结合使用 “Throughput收集器”,P85
-XX:+UseConcMarkSweepGC 使用后台线程以最低的停顿时间回收老年代的垃圾对象 如果你有充足的CPU资源可以运行后台线程,你的堆也相对较小,并且你不希望垃圾收集的停顿时间过长,就可以使用该标志 “CMS收集器”,P85
-XX:+UseParNewGC 应用线程停顿时,使用多个线程回收新生代空间 ConcMarkSweepGC标志结合使用 “CMS收集器”,P85
-XX:+UseG1GC 应用线程停顿时,使用多个线程回收新生代空间,使用后台线程回收老年代空间,以最大程度减小停顿 你有足够的CPU资源可以运行后台线程,你的堆也比较大,同时你又不希望有长时间的停顿,可以考虑使用该标志 “G1垃圾收集器”,P85

表A-3:适用于所有GC算法的通用标志

标志 功能 使用场景 更多信息
-Xms 设定堆的初始大小 如果堆的默认初始大小对于你的应用而言过小,可以考虑使用该标志 “调整堆的大小”,P92
-Xmx 设定堆的最大值 如果默认的堆大小对你的应用而言过小(或者过大),可以利用该标志调整 “调整堆的大小”,P92
-XX:NewRatio 设置新生代与老年代之间的比率 增大这个值会降低分配给新生代空间的堆的比例;减小这个值可以增大分配给新生代的堆的比率。这个设置只是一个初始值;除非自适应调整被关闭了,否则这个比率会随着垃圾收集发生变化(CMS收集器是个例外,使用CMS时新生代的大小保持恒定)。随着新生代空间的减小,新生代垃圾收集的频率会增加,Full GC的频率会降低(反之亦然) “代空间的调整”,P95
-XX:NewSize 设置新生代的初始大小 你已经清楚地了解你应用程序的需求时,就可以进行相应的设置 “代空间的调整”,P95
-XX:MaxNewSize 设置新生代的最大值 你已经清楚地了解你应用程序的需求时,就可以进行相应的设置 “代空间的调整”,P95
-Xmn 设置新生代的初始值最大值 你已经清楚地了解你应用程序的需求时,就可以进行相应的设置 “代空间的调整”,P95
-XX:PermSize=N(只适用于JDK 7) 设置永久代的初始值 如果你的应用使用了大量的类,你可能需要适当调整,增大默认值 “永久代和元空间的调整”,P96
-XX:MaxPermSize=N(只适用于JDK 7) 设置永久代的最大值 如果你的应用使用了大量的类,你可能需要适当调整,增大默认值 “永久代和元空间的调整”,P96
-XX:MetaspaceSize=N(只适用于JDK 8) 设置元空间的初始大小 如果你的应用使用了大量的类,你可能需要适当调整,增大默认值 “永久代和元空间的调整”,P96
-XX:MaxMetaspaceSize=N(只适用于JDK 8) 设置元空间的最大容量 减小这个值可以限制类的元数据占用空间大小 “永久代和元空间的调整”,P96
-XX:ParallelGCThreads=N 设置垃圾收集器使用的线程数 如果系统上同时运行了多个JVM,可以适当减小该参数值。如果JVM使用的堆非常大,又运行在一个处理能力很强的机器上,就应该适当增大这个参数值 “控制并发”,P97
-verbose:gc 开启基本的GC日志功能 GC日志应一直开启,但是这还不够,通常更详细的日志会更好 “GC工具”,P99
-Xloggc: 将GC日志记录到某个文件而非标准输出 亘古不变的是,在日志中保存这些信息总是更好的 “GC工具”,P99
-XX:+PrintGC 开启GC的基本日志 我们应该尽量开启GC日志,越详细的日志通常越有益 “GC工具”,P99
-XX:+PrintGCDetails 开启GC的详细日志 即使是在生产环境中,也应尽量开启该标志(GC日志的开销几乎可以忽略) “GC工具”,P99
-XX:+PrintGCTimeStamps 为GC日志中的每个条目打印相对时间戳 尽量开启,除非你已经开启了日期时间戳 “GC工具”,P99
-XX:+PrintGCDateStamps 为GC日志中的每个条目打印日期时间戳 相对于时间戳方式,这种方式的开销更大,不过可能更容易处理 “GC工具”,P99
-XX:+PrintReferenceGC 打印GC过程中弱引用和软引用的信息 如果程序中大量使用了这种引用,开启这个标志可以了解它们对GC开销的影响 “弱引用、软引用与其他引用”,P165
-XX:+UseGCLogFileRotation 开启GC日志循环功能以节省文件空间 在长期持续运行的生产环境中,GC日志会消耗大量的磁盘空间。在这种情况下,你可能希望开启该标志 “GC工具”,P99
-XX:NumberOfGCLogFiles=N 开启GC日志文件循环时,你可以使用该标志设定保留多少个日志文件 在长期持续运行的生产环境中,GC日志会消耗大量的磁盘空间。在这种情况下,你可能希望开启该标志 “GC工具”,P99
-XX:GCLogFileSize=N 开启日志循环时,利用该标志可以设定日志循环之前每个日志文件的大小 需要长期持续运行的生产环境中GC日志会消耗大量的磁盘空间,这种情况你可能希望开启该标志 “GC工具”,P99
-XX:+UseAdaptiveSizePolicy 设置该标志时,JVM会依据设定的GC目标调整堆的大小 如果堆的大小已经精细调优过,则可以关闭该标志 “自适应调整”,P98
-XX:+PrintAdaptiveSizePolicy 在GC日志中输出代大小调整的详细信息 通过该标志我们可以了解JVM是如何工作的。使用G1收集器时,通过该标志的输出可以了解Full GC是否源于巨型对象的分配 “自适应调整”,P98
-XX:+PrintTenuringDistribution 在GC日志中输出对象保持的信息 通过对象保持的信息我们可以判断是否需要调整对象保持的标志,以及如何调整这些标志 “晋升及Survivor空间”,P126
-XX:InitialSurvivorRatio=N 设置新生代中预留给Survivor空间的大小 如果“短寿”(short-lived)对象频繁地晋升到老年代,你可能需要考虑增大这个值 “晋升及Survivor空间”,P126
-XX:MinSurvivorRatio=N 设置新生代空间中用于自适应调整的Survivor空间大小 减小这个值会减小Survivor空间的最大值(反之亦然) “晋升及Survivor空间”,P126
-XX:TargetSurvivorRatio=N JVM试图在Survivor空间保留的空闲空间 增大这个值会缩减Survivor空间的大小(反之亦然) “晋升及Survivor空间”,P126
-XX:InitialTenuringThreshold=N JVM试图在Survivor空间保持对象的GC周期数,该参数设置的是一个初始值 增大这个值可以让对象在Survivor空间停留更长的时间,不过,需要注意的是,JVM也会对该参数进行调节 “晋升及Survivor空间”,P126
-XX:MaxTenuringThreshold=N 设置JVM可以将一个对象保持在Survivor空间的最大GC周期数 增大这个值可以让对象在Survivor空间停留更长时间;JVM会依据这个设定值与初始阈值,对实际的晋升阈值进行调整 “晋升及Survivor空间”,P126

表A-4:Throughput收集器调优标志

标志 功能 使用场景 更多信息
-XX:MaxGCPauseMillis=N 为Throughput收集器设定最长停顿时间,堆的大小会依据该目标动态调整 通常作为Throughput收集器调优的第一步,如果Throughput收集器计算出的默认堆大小无法达到应用的目标就会对其进行调整 “堆大小的自适应调整和静态调整”,P105
-XX:GCTimeRatio=N 用于控制Throughput收集器在垃圾收集上花费多少时间(时间比例),堆的大小会依据该目标动态调整 通常作为Throughput收集器调优的第一步,Throughput收集器计算出的默认堆大小如果无法达到应用的目标就会对其进行调整 “堆大小的自适应调整和静态调整”,P105
-XX:-AggressiveHeap 对于配置了大量内存的机器,如果只运行单一的虚拟机,并为该虚拟机分配了大容量的堆,使用该标志可以开启一系列的优化标志 不推荐使用该标志,理想的情况是尽可能地按照需要使用具体的调优标志 AggressiveHeap标志”,P136

表A-5:CMS收集器调优标志

标志 功能 使用场景 更多信息
-XX:CMSInitiatingOccupancyFraction=N 设定何时CMS收集器可以开启老年代空间的后台扫描 CMS收集器如果发生并发模式失效,就应该适当减少该参数的值 “理解CMS收集器”,P109
-XX:+UseCMSInitiatingOccupancyOnly 通知CMS收集器仅通过-XX:CMSInitiatingOccupancyFraction标志决定何时启动CMS后台扫描 CMSInitiatingOccupancyFraction标志一起使用 “理解CMS收集器”,P109
-XX:ConcGCThreads=N 设定CMS收集器进行后台扫描使用的线程数 CMS收集器发生并发模式失效,同时又有大量的空闲CPU资源时,可以通过该标志增加扫描线程数 “理解CMS收集器”,P109
-XX:+CMSPermGenSweepingEnabled 通知CMS收集器对永久代进行整理 采用CMS收集器的应用服务器进行了大量的类卸载时 “理解CMS收集器”,P109
-XX:CMSInitiatingPermOccupancyFraction=N 设定何时CMS收集器可以对永久代进行扫描 CMSPermGenSweepingEnAbled标志开启的同时发生了由于永久代的回收不够快导致的Full GC时 “理解CMS收集器”,P109
-XX:+CMSClassUnloadingEnabled 设定CMS收集器在永久代扫描结束后卸载类 CMSPermGenSweepingEnabled结合使用 “理解CMS收集器”,P109
-XX:+CMSIncrementalMode 以增量模式运行CMS收集 如果CPU资源有限,不过你仍然需要使用CMS收集器时 “增量式CMS垃圾收集”,P117
-XX:CMSIncrementalModeSafetyFactor=N 该参数会影响增量式CMS垃圾收集后台线程的运行频度 采用增量式CMS收集,同时又发生了并发模式失效,此时应该减小该参数 “增量式CMS垃圾收集”,P117
-XX:CMSIncrementalDutyCycleMin=N 该参数会影响增量式CMS垃圾收集后台线程运行的频度 采用增量式CMS垃圾收集,同时又发生了并发模式失效时,可以增大该参数进行调节,不过推荐的方式还是使用CMSIncrementalModeSafetyFactor “增量式CMS垃圾收集”,P117
-XX:CMSIncrementalDutyCycleMax=N 该参数会影响增量式CMS垃圾收集后台线程的运行频度 采用增量式CMS垃圾收集,同时又发生了并发模式失效时,可以增大该参数进行调节,不过推荐的方式还是使用CMSIncrementalModeSafetyFactor “增量式CMS垃圾收集”,P117
-XX:+CMSIncrementalDutyCycle 该参数会影响增量式CMS垃圾收集后台线程的运行频度 使用CMSIncrementalDutyCycleMin时,你需要设置这个标志 “增量式CMS垃圾收集”,P117

表A-6:G1收集器的调优标志

标志 功能 使用场景 更多信息
-XX:MaxGCPauseMillis=N 设置G1收集的最长停顿时间;G1收集算法会依据该参数进行相应的调整 是G1收集器调优的第一步,可以尝试调整(增大)这个值以避免发生Full GC “理解G1垃圾收集器”,P118
-XX:ConcGCThreads=N 设置G1收集后台扫描的线程数 有足够的CPU资源,同时又遭遇并发模式失效时,可以考虑调整该参数 “理解G1垃圾收集器”,P118
-XX:InitiatingHeapOccupancyPercent=N 设置何时G1收集开启后台扫描 如果G1收集发生并发模式失效,应该减小这个参数值 “理解G1垃圾收集器”,P118
-XX:G1MixedGCCountTarget=N G1收集器尝试回收老年代分区的垃圾时,要设置混合GC的次数 如果G1收集器发生了并发模式失效,减小这个值;如果混合式GC的周期过长,增大这个值 “理解G1垃圾收集器”,P118
-XX:G1HeapRegionSize=N 设置G1分区的大小 对非常大的堆,或者应用需要分配非常巨大的对象时,可以增大这个值进行调节 “G1分区的大小”,P133

表A-7:内存管理标志

标志 功能 使用场景 更多信息
-XX:+HeapDumpOnOutOfMemoryError JVM抛出一个内存异常就自动生成一个堆转储 如果应用抛出堆空间或者永久代引发的内存错误可以考虑开启这个标志,分析堆上的内存泄漏 “内存溢出错误”,P146
-XX:HeapDumpPath= 设置自动堆转储保存的文件名 由于内存错误或者GC事件引起的堆转储,可以通过这个标志指定保存路径,不再是java_pid.hprof(假设所有这些标志都已经开启) “内存溢出错误”,P146
-XX:SoftRefLRUPolicyMSPerMB=N 控制使用多长时间后软引用对象可以被回收 内存不足的情况下,减小这个值可以帮助更快地回收软引用对象 “弱引用、软引用与其他引用”,P165
-XX:MaxDirectMemorySize=N 设置通过ByteBuffer类的allocateDirect()方法可以分配多少本地内存 如果你希望限制程序能够分配的直接内存量,可以考虑使用该标志。应注意的是,分配超过64 MB直接内存的对象不需要设置这个标志 “内存占用”,P176
-XX:+UseLargePages 设置JVM,在可行的前提下,从操作系统的大页面系统中分配页面 如果操作系统支持,使用这个标志通常都能改善性能 “大页”,P182
-XX:+LargePageSizeInBytes=N 设置JVM分配指定大小的大页面(仅适用于Solaris) 在Solaris系统上,增大这个值(譬如调整到256 MB)通常能取得较好的性能 “大页”,P182
-XX:+StringTableSize=N 设置JVM用于保存内部字符串中Hashtable的大小 如果应用需要临时保存大量的字符串,可以考虑增大这个值 “字符串的保留”,P157
-XX:+UseCompressedOops 为对象引用模拟35位长的指针 这个标志对于堆的容量小于32 GB的系统默认开启,禁用该标志不会带来性能的提升 “压缩的OOP”,P185
-XX:+PrintTLAB 在垃圾收集日志中输出TLAB相关的概略信息 如果你使用的JVM不支持JFR,通过这个标志可以确保TLAB的分配是有效的 TLAB,P129
-XX:TLABSize=N 设置TLAB的大小 如果应用正在进行大量的TLAB外分配,可以通过这个标志增大TLAB的容量 TLAB,P129
-XX:-ResizeTLAB 关闭TLAB的大小调整功能 一旦设定好TLAB的大小,请确保关闭这个标志 TLAB,P129

表A-8:线程处理标志

标志 功能 使用场景 更多信息
-Xss 设置线程的本地堆栈大小 尤其是在32位Java虚拟机上,减小这个值能为JVM的其他部分留出更多的可用内存 “调节线程栈大小”,P211
-XX:-BiasedLocking 关闭Java 虚拟机的偏向锁算法 对基于线程池的应用,这个标志常常能帮助提升性能 “偏向锁”,P212

表A-9:杂项JVM调优标志

标志 功能 使用场景 更多信息
-XX:+AlwaysLockClassLoader 将类加载方案由Java 7的并行加载回退到Java 6的非并行加载 大型系统上,类的载入通常由单一线程完成,使用这个标志对启动性能有一定的提升 “类加载”,P280
-XX:-StackTraceInThrowable 关闭发生异常时,堆栈跟踪信息的收集 堆栈调用非常深的系统上,经常会抛出异常(这些场景中,修改代码,抛出更少的异常机会非常小),可以考虑使用该标志 “异常”,P287
-XX:-RestrictContended 允许非JDK代码使用@Contended注解 如果应用程序代码使用了@contended注释方式填充变量,为避免伪共享,需要设置这个标志 Contended注解”,P210
-XX:-EnableContended 禁用JDK代码中的@Contended注解 推荐开启该标志。不过在某些JDK类中,禁用该标志可以节省少量空间 Contended注解”,P210
-XX:+AggressiveOpts 启用某些尝鲜型的JVM优化。这些优化在将来的发布版本中可能会变成默认设置 你可以使用这个标志开启这些试用性质的优化进行测试,但是也要意识到这些标志随着新的JVM发布,行为可能会发生变化 AggressiveOpts标志”,P296

表A-10:Java飞行记录器控制标志

标志 功能 使用场景 更多信息
-XX:+FlightRecorder 启用Java飞行记录 器推荐开启飞行记录器,它的开销非常小,只有在实际记录发生时有少许的开销(这时的开销多少,依据使用的特性不同,会有所不同,不过总体而言还是相当小的) “Java飞行记录器”,P46
-XX:+FlightRecorderOptions 通过这个命令行标志可以设置默认的记录标志 控制JVM默认进行哪些数据的记录 “Java飞行记录器”,P46
-XX:+UnlockCommercialFeatures 允许JVM使用付费(非开源)功能 如果你购买了对应的许可,通过设置该标志可以启用Java飞行记录器的付费功能 “Java飞行记录器”,P46