1、指定垃圾收集器
- -XX:+UseSerialGC 指定使用串行垃圾收集器,新生代及老年代都是串行收集,在大堆或者多核cpu的环境中不大适合使用该种垃圾收集器
- -XX:+UseParallelGC,并行垃圾收集器,新生代使用并行收集,老年代使用串行收集
- -XX:+UseParallelOldGC,并行垃圾收器,新生代使用并行手机,老年代使用并行收集,在一些低版本的JVM该参数不支持或者不生效,这两种垃圾收集适合不在乎延时需要高吞吐的环境下使用,比如说一些批处理程序,
- -XX:+UseConcMarkSweepGC,并发垃圾收集,新生代使用并行收集,老年代采用并发收集,适合低延迟应用使用该种垃圾器。使用并发垃圾收集,相当于自动添加了参数-XX:+UseParNewGC
- -XX:+UseG1GC,使用G1垃圾收集,该种垃圾收集器比较复杂,目前在此种垃圾收集的调优经验较少,在需要大堆的应用可以考虑使用,相比并发垃圾收集器,其产生的碎片更少,且可以通过参数控制垃圾收集过程中的停顿时间。
2、调整堆大小
在描述调整堆大小参数,先用一张图描述JVM堆的分布情况:
其中新生代由Eden和s0和s1组成,有时候s0也叫做from,s1叫做to。现代JVM都是将堆分成几个不同的区间,划分的方法主要是根据对象的存活时间长短将整个jvm内存分为新生代,老年代、永久代。相应的主要参数有:
- -Xms<n>[g|m|k]:调整堆的最小大小,比如:-Xms1G,表示堆最小为1G,在系统启动阶段JVM直接向系统申请1G内存,此参数相当于参数-XX:InitialHeapSize=n[g|m|k];
- -Xmx<n>[g|m|k]:调整堆的最大大小,比如:-Xms1G表示堆最大为1G,此参数相当于参数-XX:MaxHeapSize=n[g|m|k];
- -XX:MinHeapFreeRatio=n,指定堆最小空余比例,当堆中空余内存比例小于该参数指定值时,JVM将增大内存大小直到最大堆大小,默认40;
- -XX:MaxHeapFreeRatio=n,指定堆最大空余比例,当堆中空余比例大于该参数制定值,JVM将减少内存大小,直到最小堆大小,默认为70;
JVM将在发生FGC之后,根据这两个参数调整整个对的大小,FGC一般消耗的时间较多,为了降低延迟,一般将最小堆大小和最大堆大小设置成一样的。 - -XX:NewRatio=n,老年代与新生代内存占比,-XX:NewRatio=4表示年轻代是老年代内存的1/4,也就是说年轻代占用总堆内存的1/5;
- -XX:SurvivorRatio=n,Eden区与1个survivor区域内存占比,-XX:SurvivorRatio=8,表示EdenEden区域的内存是一个survivor区域内存的8倍,一共两个survivor区域,因此survivor占用新生代的1/10;
- -XX:PermSize=<n>[g|m|k],-XX:MaxPermSize=<n>[g|m|k],这两个参数用于制定永久代内存大小,这个两个参数在jdk8中已经失效;
- -XX:MetaspaceSize=<n>[g|m|k], -XX:MaxMetaspaceSize=<n>[g|m|k],在jdk中使用这两个参数指定元数据空间大小;
- -XX:TargetSurvivorRatio=n,设定survivor区的目标使用率,默认是50%;
- -XX:MaxDirectMemorySize=<n>[g|m|k],设置直接内存的大小,在使用一些nio框架时最好设置一下此参数,此参数如果过小也有可能导致频繁触发FGC;
- -Xss<n>[g|m|k],指定Java线程栈的大小,默认值受环境影响,Xss越大,进程能运行的最大线程数就少,如果设置的过小,容易导致StackOverflowError错误;
3、收集gc日志
- -verbose:gc,输出gc日志信息,默认输出到标准输出,参数与-XX:+PrintGCDetails作用一致;
- -XX:+PrintGCDetails,打印gc日志,打印的出日志包含日志收集原因,歌区域变化情况,以及用时;
- -XX:+PrintGCDateStamps,日志中输出时间戳;
- -XX:+PrintGCTimeStamps,日志中输出时间戳,与PrintGCDateStamps参数不同的地方在于,此参数输出的时间是相对与应用启动时间的差值;
- -Xloggc:filename,把gc日志信息输入到指定文件中,
- -XX:+PrintGCApplicationStoppedTime,打印垃圾收集期间应用被暂停的时间;
- -XX:+PrintGCApplicationConcurrentTime,垃圾收集之前打印出应用未中断的执行时间;
- -XX:+UseGCLogFileRotation, -XX:GCLogFileSize=n,这两个参数用于设置gc文件滚动和设置滚动日志文件的个数,为了防止单个gc日志文件太大,生产上建议加上这两个参数;
4、CMS垃圾收集器参数
调优CMS垃圾收集器比调优吞吐量垃圾收集器复杂许多,下面列出一些用于设置CMS收集器的参数:
- -XX:CMSInitiatingOccupancyFraction=n,设置CMS垃圾收集器启动回收老年代的时机,当老年代对象占比超过n时,就启动一次CMS回收周期,注意:这个参数只是设定首次CMS垃圾回收;
- -XX:+UseCMSInitiatingOccupancyOnly,使用这个参数可以使CMS一直按照CMSInitiatingOccupancyFraction设定的值启动;
- -XX:CMSInitiatingPermOccupancyFraction=n,设置永久代内存占比超过n启动cms回收,此参数需要配合参数-XX:+CMSClassUnloadingEnabled一起使用(Java8默认开启);
- -XX:+CMSParallelInitialEnabled, 用于开启CMS initial-mark阶段采用多线程的方式进行标记,用于提高标记速度,在Java8开始已经默认开启;
- -XX:+CMSParallelRemarkEnabled,用户开启CMS remark阶段采用多线程的方式进行重新标记,默认开启;
- -XX:CMSFullGCsBeforeCompaction,我们知道cms垃圾收集器会产生内存碎片,该参数用于设置多少次CMS gc之后进行一次内存压缩;该参数默认值为0;
- -XX:+ExplicitGCInvokesConcurrent 、-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses这两个参数用户指定hotspot虚拟在执行System.gc()时使用CMS周期;
- -XX:+CMSScavengeBeforeRemark,强制hotspot虚拟机在cms remark阶段之前做一次minor gc,用于提高remark阶段的速度;
- -XX:ConcGCThreads=n,设置并发垃圾收集的线程数,默认该值是基于ParallelGCThreads计算出来的;
- -XX:+CMSPrecleaningEnabled,指定CMS是否需要进行Pre cleaning这个阶段,这个阶段的主要工作是:1、在并发标记阶段阶段由于业务线程同步在跑,新生代中对象有可能引用到老年代的对象,产生新的引用关系,这个时候需要重新标记出老年代中被引用的对象;2、老年代中对象引用关系发生变化,这个需要把引用关系发生变化的卡表(card table)标记为dirty,提高remark标记的效率;
- -XX:CMSMaxAbortablePrecleanTime=n,设置cms abortable pre阶段最长持续时间,单位为s,默认值5s。abortable prelean阶段默认在Eden区大于2M启动(通过参数:-XX:CMSScheduleRemarkEdenSizeThreshold =n设置),直到Eden区域占用率超过50%(通过参数:-XX:CMSScheduleRemarkEdenPenetration=n)时结束,同时还可以指定参数-XX:CMSMaxAbortablePrecleanLoops=n设置该阶段的循环次数(默认0,表示不限制次数),为了防止abortable pre clean阶段陷入无限等待,故设置一个最长的持续时间,达到最长持续时间之后,该阶段终止,进入remark阶段;
5、其他参数
-XX:+DisableExplicitGC,禁止hotspot执行System.gc(),默认禁用;
-XX:+ScavengeBeforeFullGC,在执行full gc之前执行一次minor gc,默认开启;
-XX:MaxTenuringThreshold=n,设定新生代的对象在经历多少次minor gc之后将转移到老年代,默认是15;
-XX:+HeapDumpOnOutOfMemoryError,在hotspot发生OOM时打印出堆,默认打印到应用工作目录,文件名称为java_pid%p.hprof;
-XX:HeapDumpPath=xx,指定hotspot虚拟机OOM时堆转储文件的path;
-XX:ErrorFile=xx,设置JVM crash时生成crash文件的路径,默认为./hs_err_pid%p.log;
-XX:+ParallelRefProcEnabled,采用多线程的方式发现需要处理的finalize方法的对象,非多线程执行对象的finalize方法;
-XX:ParallelGCThreads=n,设置并行收集的线程数,默认值采用Runtime.getRuntime().availableProcessors()来确定。不过是建立在返回值小于等于8的情况下,反之,会使用Runtime.availableProcessors()*5/8作为线程数。
-XX:+UseAdaptiveSizePolicy,开启自适应调整JAVA内存策略,在使用吞吐量垃圾收集器时,该参数用于让jvm自行调整Eden区和Survivor区空间的大小,新生代与老年代空间的大小;
-XX:+PrintAdaptiveSizePolicy,可以打印出survivor的一些详细信息,关于survivor区间是否溢出,是否有对象转移到老年代;
-XX:+PrintTenuringDistribution,显示出survivor区间有效对象的年龄分布情况,可以通过该参数的输出确定出survivor大小以及MaxTenuringThreshold的值;
-XX:MaxGCPauseMillis=n,设置最大gc停顿时间,这个时间不是设置的越小越好,此参数只在ps收集器上有效,不建议修改此参数的值;
-XX:GCTimeRatio,设置垃圾收集时间占总时间的比率,默认为99,也就是说垃圾收集时间占用总时间的1%,此参数只在ps收集器上有效;
-XX:+HeapDumpAfterFullGC,在执行一次FGC之后打印出Heap到文件;
-XX:+HeapDumpBeforeFullGC,在执行一次FGC之前打印出Heap到文件,这两个参数主要用于调试;
-XX:+PrintHeapAtGC,打印gc前后堆详细信息,不管是minor gc还是full gc都会打印;
-XX:+GCLockerInvokesConcurrent,在执行gc之前都需要先先查看 gc locker是否被java线程持有,如果存在gc locker被持有的情况则忽略此次gc,在所有java线程完全释放gc locker之后补偿一次gc。此参数指定,如果是fgc的话,则补偿一次CMS back groud fgc。
-XX:ReservedCodeCacheSize=<n>[g|m|k]、-XX:InitialCodeCacheSize=<n>[g|m|k],指定代码缓存的大小,用于保存已编译方法生成的本地代码,如果代码缓存被占满JVM会发出警告信息,并切换到interpreted-only模式,JIT编译器被停用,字节码将不会再编译成机器码。这样的话对JVM的性能影响很大;
-XX:+UseCodeCacheFlushing,如果代码缓存不断增长导致代码缓存空间不够,使用该参数让jvm放弃一些被编译的代码,避免代码缓存被占满时JVM切换到interpreted-only的情况;
-
-XX:+DoEscapeAnalysis,开启逃逸分析,逃逸分析是一种分析对象范围的技术,在一些情况一个线程分配的对象可能会被其他对象使用,这种现象叫做“逃逸”,如果一个对象没有“逃逸”,则可以运用一些额外的优化技术,这种优化技术“逃逸分析”。通过“逃逸分析” JIT可以使用如下技术优化:
- 栈上分配
- 消灭同步
- 消灭垃圾回收读写障碍
- 对象爆炸
-XX:+UseBiasedLocking,开启偏向锁,偏向锁是是锁偏爱上次使用它的线程,在非竞争锁的场景下,可以实现无锁的开销。
-XX:+UseLargePages,开启使用大页面,使用大页面可以提高TLB(translation lookaside buffer(转换后备缓存区))的缓存命中率;
-XX:PretenureSizeThreshold=n,指定对象占用的字节数超过n之后直接在老年代中分配,默认值0,表示最大值;
-XX:+OmitStackTraceInFastThrow,一些频繁抛出的异常,JVM为了性能优化而抛出没有堆栈的异常,默认开启,
-XX:+PrintFlagsInitial、-XX:+PrintFlagsFinal,打印出设置的JVM参数和最终生效的JVM参数和他们的值,-XX:+PrintCommandLineFlags打印出被修改的JVM参数,一般在启动应用添加此参数打印出引用启动时添加的JVM参数,在应用运行过程中一些JVM参数可能会被修改掉(通过jinfo工具);
-XX:+PrintSafepointStatistics,打印安全点统计信息,-XX:PrintSafepointStatisticsCount=n设置打印安全点统计信息的次数;
-XX:+PrintReferenceGC,打印gc时处理的reference情况;
-XX:+UseCompressedOops,开启压缩指针,压缩指针主要是为了解决32位操作系统内存寻址范围只有4G的限制,开启压缩指针最大寻址范围增加到32G;如果内存超过32G(Xmx>32G),开启该参数无效;
-XX:+ParallelRefProcEnabled,使用此参数激活多线程方式的引用处理,截止到目前的jdk8该参数默认关闭,如果在gc中发现处理ref处理的时间过长,可以通过参数-XX:+PrintReferenceGC打印出每次垃圾收集中记录每个引用对象类型的统计数据,另外如果发现有大量软引用正在被处理,可以使用参数-XX:SoftRefLRUPolicyPerMB调整软件用的处理策略,该参数的默认值为1000(ms),该参数的含义是,使用该参数设置的值乘以java堆可用空间(以兆为单位)的出来的值,若软引用在这段时间内没有被访问,那么这些软引用将会被回收,调优引用处理的目标主要有两点:第一是降低引用在gc过程中处理时间,第二是降低heap的占用空间,减少垃圾收集频率和最终需要复制的时间;
总结
本文列举了一些常用的JVM参数,至于如何调整各参数已达到JVM的最佳性能要以场景而定,
链接:https://www.jianshu.com/p/12eda04e6f87
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。