jvm 可配置的参数选项能够参考 Oracle 官方网站给出的相关信息:http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
下面只列举其中的几个经常使用和容易掌握的配置选项html
配置参数 | 功能 |
---|---|
-Xms | 初始堆大小。如:-Xms256m |
-Xmx | 最大堆大小。如:-Xmx512m |
-Xmn | 新生代大小。一般为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90% |
-Xss | JDK1.5+ 每一个线程堆栈大小为 1M,通常来讲若是栈不是很深的话, 1M 是绝对够用了的。 |
-XX:NewRatio | 新生代与老年代的比例,如 –XX:NewRatio=2,则新生代占整个堆空间的1/3,老年代占2/3 |
-XX:SurvivorRatio | 新生代中 Eden 与 Survivor 的比值。默认值为 8。即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10 |
-XX:PermSize | 永久代(方法区)的初始大小 |
-XX:MaxPermSize | 永久代(方法区)的最大值 |
-XX:+PrintGCDetails | 打印 GC 信息 |
-XX:+HeapDumpOnOutOfMemoryError | 让虚拟机在发生内存溢出时 Dump 出当前的内存堆转储快照,以便分析用 |
注意:PermSize永久代的概念在jdk1.8中已经不存在了,取而代之的是metaspace元空间,当认为执行永久代的初始大小以及最大值是jvm会给出如此下提示:
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=30m; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=30m; support was removed in 8.0java
从前面的3篇文章中,咱们分析了5个垃圾收集器,还有一些 GC 的算法,那么,在 GC 调优中,咱们确定会先判断哪里出现的问题,而后再根据出现的问题进行调优,而调优的手段就是 JVM 提供给咱们的那些参数或者说选项,这些参数将会改变 GC 的运行方式。所以,他们显得极为重要。ios
咱们将每个垃圾收集器相关的参数一个一个娓娓道来,注意,楼主推荐一个小程序:前阿里 JVM 大神寒泉子的公众号里面有个小程序------JVM Pocket,这个小程序介绍了全部的 JVM 参数的做用,你能够在里面搜索你想知道的参数,也能够把你了解的参数写上去供你们参考。公众号:lovestblog。git
值得注意的一点是,这些参数可能会重复,还记得咱们以前的那张图吗,楼主以为有必要再发一次:程序员
能够看到,这些收集器会有一些重复,并且,某些参数也是会做用于全部的处理器,所以,咱们下面的介绍可能会有一些重复。github
还有一点就是,JVM 为咱们设置了不少默认的参数,可是,若是能够的话,仍是建议使用显式的声明,这样更能表达意图。不然,别人不必定知道咱们是否知道这些默认值。web
咱们开始咱们的参数之旅吧!面试
串行收集器,client 的默认收集器,分为年轻代 Serial 和老年代 Serial Old 收集器。正则表达式
-XX:+UseSerialGC 这个参数就是能够指定使用新生代串行收集器和老年代串行收集器, “+” 号的意思是ture,开启,反之,若是是 “-”号,则是关闭。redis
-XX:+UseParNewGC 新生代使用 ParNew 回收器,老年代使用串行收集器。
-XX:+UseParallelGC 新生代私用 ParallelGC 回收器,老年代使用串行收集器。
而 Serial 收集器出现的日志为 DefNew .
并行收集器是 Serial 的多线程版本,在 CPU 并行能力强大的计算机上有很大优点。
其中:
-XX:+UseParNewGC 上面说过了,新生代使用 ParNew 收集器,老年代使用串行收集器。
-XX:+UseConcMarkSweepGC: 新生代使用 ParNew 回收器,老年代使用 CMS。
-XX:ParallelGCThreads={value} 这个参数是指定并行 GC 线程的数量,通常最好和 CPU 核心数量至关。默认状况下,当 CPU 数量小于8, ParallelGCThreads 的值等于 CPU 数量,当 CPU 数量大于 8 时,则使用公式:3+((5*CPU)/ 8);同时这个参数只要是并行 GC 均可以使用,不仅是 ParNew。
而 ParNew 的 GC 日志则表吸纳出 ParNew。
全称 Parallel Scavenge 收集器,该收集器是 Java 8 的默认收集器,由于它可以根据系统当前状态给出吞吐量最高的GC 配置。因此,在一些手工调优复杂的场合或者对实时性要求不高的场合,可使用该处理器。
有哪些参数呢?
-XX:MaxGCPauseMillis 设置最大垃圾收集停顿时间,他的值是一个大于0的整数。ParallelGC 工做时,会调整 Java 堆大小或者其余的一些参数,尽量的把停顿时间控制在 MaxGCPauseMillis 之内。若是为了将停顿时间设置的很小,将此值也设置的很小,那么 PS 将会把堆设置的也很小,这将会到值频繁 GC ,虽然系统停顿时间小了,但总吞吐量降低了。
-XX:GCTimeRatio 设置吞吐量大小,他的值是一个0 到100之间的整数,假设 GCTimeRatio 的值是 n ,那么系统将花费不超过 1/(1+n) 的时间用于垃圾收集,默认 n 是99,即不超过1% 的时间用于垃圾收集。
-XX:+UseParallelGC 新生代使用 ParallelGC 回收器,老年代使用串行回收器。
-XX:+UseParallelOldGC 新生代使用 ParallelGC 回收器,老年代使用 ParallelOldGC 回收器。
-XX:UseAdaptiveSizePolicy: 打开自适应策略。在这种模式下,新生代的大小,eden 和 Survivor 的比例,晋升老年代的对象年龄等参数会被自动调整。以达到堆大小,吞吐量,停顿时间的平衡点。
聪明的同窗相比看出来了,1 和 2 两个参数是矛盾的。由于吞吐量和停顿时间就是矛盾的。因此,要根据应用的特性来进行设置,以达到最优水平。
同时,Parallel Old 收集器也是一种关注吞吐量的并行的老年代回收器。
-XX:+UseParallelOldGC 新生代使用 ParallelGC 回收器,老年代使用 ParallelOldGC 回收器。该参数能够启用 ParallelOldGC。
-XX:ParallelGCGThreads 同时能够指定该参数设置并行线程数量。
而 PS 处理器的 GC 日志则是 PSYoungGen。
CMS 处理器关注的是停顿时间。全称 Concurrent Mark Sweep。由于该处理器较为复杂,所以可使用较多参数。
-XX:-CMSPrecleaningEnabled 不进行预清理,度过咱们以前的文章的都知道,CMS 在并发标记和从新标记的这段时间内,会有一个预清理的工做,而这个经过会尝试5秒以内等待来一次 YGC。以避免在后面的从新标记阶段耗费大量时间来标记新生代的对象。
-XX:+UseConcMarkSweepGC 此参数将启动 CMS 回收器。默认新生代是 ParNew,也能够设置 Serial 为新生代收集器。该参数等价于 -Xconcgc。
-XX:ParallelGCThreads 因为是并行处理器,固然也能够指定线程数。默认并发线程数是:(ParallelGCThreads + 3)/ 4)。
-XX:ConcGCThreads 或者 -XX:ParallelCMSThreads ;除了上面设置线程的方式,你也能够经过这个两个参数任意一个手工设定 CMS 并发线程数。
-XX:CMSInitiatingOccupancyFraction 因为 CMS 回收器不是独占式的,在垃圾回收的时候应用程序仍在工做,因此须要留出足够的内存给应用程序,不然会触发 FGC。而何时运行 CMS GC 呢?经过该参数便可设置,该参数表示的是老年代的内存使用百分比。当达到这个阈值就会执行 CMS。默认是68。 若是老年代内存增加很快,建议下降阈值,避免 FGC,若是增加慢,则能够加大阈值,减小 CMS GC 次数。提升吞吐量。
-XX:+UseCMSCompactAtFullCollection 因为 CMS 使用标记清理算法,内存碎片没法避免。该参数指定每次 CMS 后进行一次碎片整理。
-XX:CMSFullGCsBeforeCompaction 因为每次进行碎片整理将会影响性能,你可使用该参数设定多少次 CMS 后才进行一次碎片整理,也就是内存压缩。
-XX:+CMSClassUnloadingEnabled 容许对类元数据进行回收。
-XX:CMSInitiatingPermOccupancyFraction 当永久区占用率达到这一百分比时,启动 CMS 回收(前提是 -XX:+CMSClassUnloadingEnabled 激活了)。
-XX:UseCMSInitiatingOccupancyOnly 表示只在到达阈值的时候才进行 CMS 回收。
XX:CMSWaitDuration=2000 因为CMS GC 条件比较简单,JVM有一个线程定时扫描Old区,时间间隔能够经过该参数指定(毫秒单位),默认是2s。
CMS 的 GC 日志 就是 CMS。
做为 Java 9 的默认垃圾收集器,该收集器和以前的收集器大不相同,该收集器能够工做在young 区,也能够工做在 old 区。有哪些参数呢?
-XX:+UseG1GC 开启 G1 收集器。
-XX:MaxGCPauseMillis 用于指定最大停顿时间,若是任何一次停顿超过这个设置值时,G1 就会尝试调整新生代和老年代的比例,调整堆大小,调整晋升年龄的手段,试图达到目标。和 PS 同样,停顿时间小了,对应的吞吐量也会变小。这点值得注意。
-XX:ParallelGCThreads 因为是并行并发的,能够指定GC 工做线程数量。
-XX:InitiatingHeapOccupancyPercent 该参数能够指定当整个堆使用率达到多少时,触发并发标记周期的执行。默认值时45,即当堆的使用率达到45%,执行并发标记周期,该值一旦设置,始终都不会被 G1修改。也就是说,G1 就算为了知足 MaxGCPauseMillis 也不会修改此值。若是该值设置的很大,致使并发周期迟迟得不到启动,那么引发 FGC 的概率将会变大。若是太小,则会频繁标记,GC 线程抢占应用程序CPU 资源,性能将会降低。
-XX:GCPauseIntervalMillis 设置停顿时间间隔。
在 GC 调优中,还有一些通用的参数。一般是咱们的好帮手。
-XX:-+DisableExplicitGC 禁用 System.gc(),因为该方法默认会触发 FGC,而且忽略参数中的 UseG1GC 和 UseConcMarkSweepGC,所以必要时能够禁用该方法。
-XX:+ExplicitGCInvokesConcurrent 该参数能够改变上面的行为,也就是说,System.gc() 后不使用 FGC ,而是使用配置的并发收集器进行并发收集。注意:使用此选项就不要 使用 上面的选项。
-XX:-ScavengeBeforeFullGC 因为大部分 FGC 以前都会 YGC,减轻了 FGC 的压力,缩短了 FGC 的停顿时间,但也可能你不须要这个特性,那么你可使用这个参数关闭,默认是 ture 开启。
-XX:MaxTenuringThreshold={value} 新生代 to 区的对象在通过屡次 GC 后,若是尚未死亡,则认为他是一个老对象,则能够晋升到老年代,而这个年龄(GC 次数)是能够设置的,有就是这个参数。默认值时15。超过15 则认为是无限大(由于age变量时4个 bit,超过15没法表达)。但该参数不是惟一决定对象晋升的条件。当 to 区不够或者改对象年龄已经达到了平均晋升值或者大对象等等条件。
-XX:TargetSurvivorRatio={value} 决定对什么时候晋升的不只只有 XX:MaxTenuringThreshold 参数,若是在 Survivor 空间中相同年龄全部对象大小的总和大鱼 Survivor 空间的一半(默认50%),年龄大于或等于该年龄的对象就能够直接进入老年代。无需在意 XX:MaxTenuringThreshold参数。所以,MaxTenuringThreshold 只是对象晋升的最大年龄。若是将 TargetSurvivorRatio 设置的很小,对象将晋升的很快。
-XX:PretenureSizeThresholds={value} 除了年龄外,对象的体积也是影响晋升的一个关键,也就是大对象。若是一个对象新生代放不下,只能直接经过分配担保机制进入老年代。该参数是设置对象直接晋升到老年代的阈值,单位是字节。只要对象的大小大于此阈值,就会直接绕过新生代,直接进入老年代。注意:这个参数只对 Serial 和 ParNew 有效,ParallelGC 无效,默认状况下该值为0,也就是不指定最大的晋升大小,一切有运行状况决定。
-XX:-UseTLAB 禁用线程本地分配缓存。TLAB 的全称是 Thread LocalAllocation Buffer ,即线程本地线程分配缓存,是一个线程私有的内存区域。该设计是为了加速对象分配速度。因为对象通常都是分配在堆上,而对是线程共享的。所以确定有锁,虽然使用 CAS 的操做,但性能仍有优化空间。经过为每个线程分配一个 TLAB 的空间(在 eden 区),能够消除多个线程同步的开销。默认开启。
-XX:TLABSize 指定 TLAB 的大小。
-XX:+PrintTLAB 跟踪 TLAB 的使用状况。用以肯定是用多大的 TLABSize。
-XX:+ResizeTLAB 自动调整 TLAB 大小。
同时,对象也可能会在栈上分配,栈上分配,TLAB 分配,堆分配,他们的流程以下:
对象分配流程
还有一些开启 GC 日志的参数,是 GC 调优不可或缺的工具。
-XX:+PrintGCDateStamps 打印 GC 日志时间戳。
-XX:+PrintGCDetails 打印 GC 详情。
-XX:+PrintGCTimeStamps: 打印这次垃圾回收距离jvm开始运行的所耗时间。
-Xloggc:<filename> 将垃圾回收信息输出到指定文件
-verbose:gc 打印 GC 日志
-XX:+PrintGCApplicationStopedTime 查看 gc 形成的应用暂停时间
XX:+PrintTenuringDistribution, 对象晋升的日志
-XX:+HeapDumpOnOutOfMemoryError 内存溢出时输出 dump 文件。
好了,咱们已经将一些经常使用的 GC 参数介绍了,固然会有遗漏的,若有遗漏或者介绍有误的,请告知本人。这些参数不只仅是为了服务你们,同时也是本身作的一个总结,之后就不用处处找了。说白了这就是写博客的好处:总结了本身,也作了备份,同时也可能帮助了别人。
做者:莫那一鲁道
连接:https://www.jianshu.com/p/74d126dd5544
來源:简书
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。
Nov 2nd, 2016 Posted by 飒然Hang in java
对于调优这个事情来讲,通常就是三个过程:
Java调优也不外乎这三步。
此外,本文所讲的性能分析、调优等是抛开如下因素的:
调优是须要作好准备工做的,毕竟每个应用的业务目标都不尽相同,性能瓶颈也不会总在同一个点上。在业务应用层面,咱们须要:
此外,咱们还须要了解Java相关的一些知识:
在系统层面可以影响应用性能的通常包括三个因素:CPU、内存和IO,能够从这三方面进行程序的性能瓶颈分析。
当程序响应变慢的时候,首先使用top、vmstat、ps等命令查看系统的cpu使用率是否有异常,从而能够判断出是不是cpu繁忙形成的性能问题。其中,主要经过us(用户进程所占的%)这个数据来看异常的进程信息。当us接近100%甚至更高时,能够肯定是cpu繁忙形成的响应缓慢。通常说来,cpu繁忙的缘由有如下几个:
肯定好cpu使用率最高的进程以后就可使用jstack来打印出异常进程的堆栈信息:
jstack [pid]
接下来须要注意的一点是,Linux下全部线程最终仍是以轻量级进程的形式存在系统中的,而使用jstack只能打印出进程的信息,这些信息里面包含了此进程下面全部线程(轻量级进程-LWP)的堆栈信息。所以,进一步的须要肯定是哪个线程耗费了大量CPU,此时可使用top -p [processId] -H来查看,也能够直接经过ps -Le来显示全部进程,包括LWP的资源耗费信息。最后,经过在jstack的输出文件中查找对应的LWP的id便可以定位到相应的堆栈信息。其中须要注意的是线程的状态:RUNNABLE、WAITING等。对于Runnable的进程须要注意是否有耗费cpu的计算。对于Waiting的线程通常是锁的等待操做。
也可使用jstat来查看对应进程的gc信息,以判断是不是gc形成了cpu繁忙。
jstat -gcutil [pid]
还能够经过vmstat,经过观察内核状态的上下文切换(cs)次数,来判断是不是上下文切换形成的cpu繁忙。
vmstat 1 5
此外,有时候可能会由jit引发一些cpu飚高的情形,如大量方法编译等。这里可使用-XX:+PrintCompilation这个参数输出jit编译状况,以排查jit编译引发的cpu问题。
对Java应用来讲,内存主要是由堆外内存和堆内内存组成。
堆外内存
堆外内存主要是JNI、Deflater/Inflater、DirectByteBuffer(nio中会用到)使用的。对于这种堆外内存的分析,仍是须要先经过vmstat、sar、top、pidstat(这里的sar,pidstat以及iostat都是sysstat软件套件的一部分,须要单独安装)等查看swap和物理内存的消耗情况再作判断的。此外,对于JNI、Deflater这种调用能够经过Google-preftools来追踪资源使用情况。
堆内内存
此部份内存为Java应用主要的内存区域。一般与这部份内存性能相关的有:
以上使用不当很容易形成:
排查堆内存问题的经常使用工具是jmap,是jdk自带的。一些经常使用用法以下:
此外,无论是使用jmap仍是在OOM时产生的dump文件,可使用Eclipse的MAT(MEMORY ANALYZER TOOL)来分析,能够看到具体的堆栈和内存中对象的信息。固然jdk自带的jhat也可以查看dump文件(启动web端口供开发者使用浏览器浏览堆内对象的信息)。此外,VisualVM也可以打开hprof文件,使用它的heap walker查看堆内存信息。
一般与应用性能相关的包括:文件IO和网络IO。
文件IO
可使用系统工具pidstat、iostat、vmstat来查看io的情况。这里能够看一张使用vmstat的结果图。
这里主要注意bi和bo这两个值,分别表示块设备每秒接收的块数量和块设备每秒发送的块数量,由此能够断定io繁忙情况。进一步的能够经过使用strace工具定位对文件io的系统调用。一般,形成文件io性能差的缘由不外乎:
网络IO
查看网络io情况,通常使用的是netstat工具。能够查看全部链接的情况、数目、端口信息等。例如:当time_wait或者close_wait链接过多时,会影响应用的相应速度。
netstat -anp
此外,还可使用tcpdump来具体分析网络io的数据。固然,tcpdump出的文件直接打开是一堆二进制的数据,可使用wireshark阅读具体的链接以及其中数据的内容。
tcpdump -i eth0 -w tmp.cap -tnn dst port 8080 #监听8080端口的网络请求并打印日志到tmp.cap中
还能够经过查看/proc/interrupts来获取当前系统使用的中断的状况。
各个列依次是:
irq的序号, 在各自cpu上发生中断的次数,可编程中断控制器,设备名称(request_irq的dev_name字段)
经过查看网卡设备的终端状况能够判断网络io的情况。
上面分别针对CPU、内存以及IO讲了一些系统/JDK自带的分析工具。除此以外,还有一些综合分析工具或者框架能够更加方便咱们对Java应用性能的排查、分析、定位等。
VisualVM
这个工具应该是Java开发者们很是熟悉的一款java应用监测工具,原理是经过jmx接口来链接jvm进程,从而可以看到jvm上的线程、内存、类等信息。若是想进一步查看gc状况,能够安装visual gc插件。此外,visualvm也有btrace的插件,能够可视化直观的编写btrace代码并查看输出日志。 与VisualVm相似的,jconsole也是经过jmx查看远程jvm信息的一款工具,更进一步的,经过它还能够显示具体的线程堆栈信息以及内存中各个年代的占用状况,也支持直接远程执行MBEAN。固然,visualvm经过安装jconsole插件也能够拥有这些功能。
但因为这俩工具都是须要ui界面的,所以通常都是经过本地远程链接服务器jvm进程。服务器环境下,通常并不用此种方式。
Java Mission Control(jmc)
此工具是jdk7 u40开始自带的,原来是JRockit上的工具,是一款采样型的集诊断、分析和监控与一体的很是强大的工具: https://docs.oracle.com/javacomponents/jmc-5-5/jmc-user-guide/toc.htm。可是此工具是基于JFR(jcmd JFR.start name=test duration=60s settings=template.jfc filename=output.jfr)的,而开启JFR须要商业证书:jcmdVM.unlock_commercial_features。
Btrace
这里不得不提的是btrace这个神器,它使用java attach api+ java agent + instrument api可以实现jvm的动态追踪。在不重启应用的状况下能够加入拦截类的方法以打印日志等。具体的用法能够参考Btrace入门到熟练小工彻底指南。
Jwebap
Jwebap是一款JavaEE性能检测框架,基于asm加强字节码实现。支持:http请求、jdbc链接、method的调用轨迹跟踪以及次数、耗时的统计。由此能够获取最耗时的请求、方法,并能够查看jdbc链接的次数、是否关闭等。但此项目是2006年的一个项目,已经将近10年没有更新。根据笔者使用,已经不支持jdk7编译的应用。若是要使用,建议基于原项目二次开发,同时也能够加入对redis链接的轨迹跟踪。固然,基于字节码加强的原理,也能够实现本身的JavaEE性能监测框架。
上图来自笔者公司二次开发过的jwebap,已经支持jdk8和redis链接追踪。
useful-scripts
这里有一个本人参与的开源的项目:https://github.com/superhj1987/useful-scripts,封装了不少经常使用的性能分析命令,好比上文讲的打印繁忙java线程堆栈信息,只须要执行一个脚本便可。
与性能分析相对应,性能调优一样分为三部分。
此外,使用多线程的时候,还须要注意如下几点:
内存的调优主要就是对jvm的调优。
其中,对于第一点,具体的还有一点建议:
通常吞吐量优先的应用都应该有一个很大的年轻代和一个较小的年老代。这样能够尽量回收掉大部分短时间对象,减小中期的对象,而年老代存放长期存活对象。
此外,较小堆引发的碎片问题:由于年老代的并发收集器使用标记、清除算法,因此不会对堆进行压缩。当收集器回收时,会把相邻的空间进行合并,这样能够分配给较大的对象。可是,当堆空间较小时,运行一段时间之后,就会出现“碎片”,若是并发收集器找不到足够的空间,那么并发收集器将会中止,而后使用传统的标记、清除方式进行回收。若是出现“碎片”,可能须要进行以下配置:-XX:+UseCMSCompactAtFullCollection,使用并发收集器时,开启对年老代的压缩。同时使用-XX:CMSFullGCsBeforeCompaction=xx设置多少次Full GC后,对年老代进行压缩。
其他对于jvm的优化问题可见后面JVM参数进阶一节。
代码上,也须要注意:
不要用Log4j输出文件名、行号,由于Log4j经过打印线程堆栈实现,生成大量String。此外,使用log4j时,建议此种经典用法,先判断对应级别的日志是否打开,再作操做,不然也会生成大量String。
if (logger.isInfoEnabled()) { logger.info(msg); }
文件IO上须要注意:
网络IO上须要注意:
此外,jdk七、8在jvm的性能上作了一些加强:
此外,网上还有不少过期的建议,不要再盲目跟随:
jvm的参数设置一直是比较理不清的地方,不少时候都搞不清都有哪些参数能够配置,参数是什么意思,为何要这么配置等。这里主要针对这些作一些常识性的说明以及对一些容易让人进入陷阱的参数作一些解释。
启动参数默认值
Java有不少的启动参数,并且不少版本都并不同。可是如今网上充斥着各类资料,若是不加辨别的所有使用,不少是没有效果或者原本就是默认值的。通常的,咱们能够经过使用java -XX:+PrintFlagsInitial来查看全部能够设置的参数以及其默认值。也能够在程序启动的时候加入-XX:+PrintCommandLineFlags来查看与默认值不相同的启动参数。若是想查看全部启动参数(包括和默认值相同的),可使用-XX:+PrintFlagsFinal。
输出里“=”表示使用的是初始默认值,而“:=”表示使用的不是初始默认值,多是命令行传进来的参数、配置文件里的参数或者是ergonomics自动选择了别的值。
此外,还可使用jinfo命令显示启动的参数。
这里须要指出的是,当你配置jvm参数时,最好是先经过以上命令查看对应参数的默认值再肯定是否须要设置。也最好不要配置你搞不清用途的参数,毕竟默认值的设置是有它的合理之处的。
动态设置参数
当Java应用启动后,定位到了是GC形成的性能问题,可是你启动的时候并无加入打印gc的参数,不少时候的作法就是从新加参数而后重启应用。但这样会形成必定时间的服务不可用。最佳的作法是可以在不重启应用的状况下,动态设置参数。使用jinfo能够作到这一点(本质上仍是基于jmx的)。
jinfo -flag [+/-][flagName] [pid] #启用/禁止某个参数 jinfo -flag [flagName=value] [pid] #设置某个参数
对于上述的gc的状况,就可使用如下命令打开heap dump并设置dump路径。
jinfo -flag +HeapDumpBeforeFullGC [pid] jinfo -flag +HeapDumpAfterFullGC [pid] jinfo -flag HeapDumpPath=/home/dump/dir [pid]
一样的也能够动态关闭。
jinfo -flag -HeapDumpBeforeFullGC [pid] jinfo -flag -HeapDumpAfterFullGC [pid]
其余的参数设置相似。
-verbose:gc 与 -XX:+PrintGCDetails
不少gc推荐设置都同时设置了这两个参数,其实,只要打开了-XX:+PrintGCDetails,前面的选项也会同时打开,无须重复设置。
-XX:+DisableExplicitGC
这个参数的做用就是使得system.gc变为空调用,不少推荐设置里面都是建议开启的。可是,若是你用到了NIO或者其余使用到堆外内存的状况,使用此选项会形成oom。能够用XX:+ExplicitGCInvokesConcurrent或XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses(配合CMS使用,使得system.gc触发一次并发gc)代替。
此外,还有一个比较有意思的地方。若是你不设置此选项的话,当你使用了RMI的时候,会周期性地来一次full gc。这个现象是因为分布式gc形成的,为RMI服务。具体的可见此连接内容中与dgc相关的:http://docs.oracle.com/javase/6/docs/technotes/guides/rmi/sunrmiproperties.html
MaxDirectMemorySize
此参数是设置的堆外内存的上限值。当不设置的时候为-1,此值为-Xmx减去一个survivor space的预留大小。
因为遗留缘由,做用相同的参数
-XX:MaxTenuringThreshold
使用工具查看此值默认值为15,可是选择了CMS的时候,此值会变成4。当此值设置为0时,全部eden里的活对象在经历第一次minor GC的时候就会直接晋升到old gen,survivor space直接就没用。还有值得注意的一点,当使用并行回收器时,此值是没有做用的,并行回收器默认是自动调整这些参数以求达到吞吐量最大的。此外,即便是使用CMS等回收器,晋升到老年代的age也不是不变的,当某一age的对象的大小达到年轻代的50%时,这个age会被动态调整为晋升年龄。
-XX:HeapDumpPath
使用此参数能够指定-XX:+HeapDumpBeforeFullGC、-XX:+HeapDumpAfterFullGC、-XX:+HeapDumpOnOutOfMemoryError触发heap dump文件的存储位置。
-XX:+UseAdaptiveSizePolicy
此参数在并行回收器时是默认开启的,会根据应用运行情况作自我调整,如MaxTenuringThreshold、survivor区大小等。其中第一次晋升老年代的年龄以InitialTenuringThreshold(默认为7)开始,后续会自动调整。若是但愿跟踪每次minor GC后新的存活周期的阈值,可在启动参数上增长:-XX:+PrintTenuringDistribution。若是想要能够配置这些参数,能够关闭此选项,但paralle的性能很难达到最佳。其余垃圾回收期则慎重开启此开关。
微信公众号【Java技术江湖】一位阿里 Java 工程师的技术小站。(关注公众号后回复”Java“便可领取 Java基础、进阶、项目和架构师等免费学习资料,更有数据库、分布式、微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送做者原创的Java学习指南、Java程序员面试指南等干货资源)