可以看到堆内存为2G,新生代为768M老年代为1280M,新生代采用ParNew收集器
-XX:+UseConcMarkSweepGC:新生代使用ParNew回收器,老年代使用CMS
线程栈为512k(默认1024k调小可以增加创建线程数,增加并发量)
同时打印 GC 详细信息和打印 GC 发生时间,当发生OOM时,Dump文件到指定路径
栈空间参数设置
-Xss: 设置线程的最大栈空间,栈空间越大,方法的递归深度越大
方法区参数设置(方法区大小的参数设置跟jdk版本相关)
jdk1.6,jdk1.7设置方法区永久代的大小
-XX:PermSize=5M
-XX:MaxPermSize=5M 最大永久代的大小默认是64M
jdk1.8及以上,永久代被移除,取而代之的是元数据区,元数据区是一块堆外的直接内存
如果不指定大小,那么会耗尽所有可用的系统内存
-XX:MaxMetaspaceSize=60M 设置最大元数据的大小
堆设置
-Xms:初始堆大小
-Xmx:最大堆大小
-Xmn:设置新生代大小,设置较大的新生代大小会减小老年代大小,新生代的大小一般为堆空间的1/3
-XX:NewSize=n: 设置年轻代大小
-XX:NewRatio=n:设置年轻代和年老代的比值(老年代/新生代)。如:为3,表示年轻代与年老代比值为1:3
年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。
-Xmn,-XX:NewSize/-XX:MaxNewSize,-XX:NewRatio 3组参数都可以影响年轻代的大小,混合使用的情况下,优先级是什么?
1.高优先级:-XX:NewSize/-XX:MaxNewSize
2.中优先级:-Xmn(默认等效 -Xmn=-XX:NewSize=-XX:MaxNewSize=?)
3.低优先级:-XX:NewRatio
推荐使用-Xmn参数,原因是这个参数简洁,相当于一次设定 NewSize/MaxNewSIze而且两者相等,适用于生产环境。
-Xmn 配合 -Xms/-Xmx,即可将堆内存布局完成 -Xmn参数是在JDK 1.4 开始支持
下面两个参数配合使用,当系统发生堆空间不足时,会导出整个堆的信息,且导出到指定的文件中去,后面用MAT工具分析
-XX:HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=d:/a.dump
直接内存配置
-XX:MaxDirectMemorySize
设置直接内存大小,如果不设置,默认值为最大堆空间,即-Xmx指定的大小,当达到指定值时,
会触发垃圾回收,如果回收后也无法释放空间,那么将会抛出OOM
-XX:+UseSerialGC:新生代,老年代都使用串行收集器
-XX:+UseParNewGC:新生代使用ParNew收集器,老年代使用串行收集器Serial
(jdk9,10已经废除,因为ParNew只能和CMS收集器配合使用,而jdk9,10使用的默认收集器是G1)
-XX:+UseParallelGC:新生代使用ParallelGC,老年代使用串行收集器Serial
-XX:+UseParallelGC:新生代使用ParallelGC回收器,老年代使用串行回收器Serial
-XX:+UseParallelOldGC:新生代使用ParallelGC回收器,老年代使用ParallelOldGc回收器
两个重要参数
-XX:MaxGCPasuseMillis:设置最大垃圾回收停顿时间,设置的过小,可能导致垃圾回收频率加大
-XX:GCTimeRatio:设置吞吐量大小,取值范围为0-100,系统回收垃圾的停顿时间花费不超过1/(1+n)%
设置线程数量
-XX:ParallelGCThreads
-XX:+UseConcMarkSweepGC:新生代使用ParNew回收器,老年代使用CMS
CMS默认启动的并发线程数量为(parallelGCTheads+3)/4
设置并发线程数
-XX:ConcGCThreads=n
-XX:ParallelGCThreads=n
设置老年代空间使用率达到多少时执行CMS垃圾回收
-XX:CMSInitiatingOccupancyFraction 默认值为68
碎片整理参数,如果碎片不整理,可能造成没达到阈值就会触发老年代垃圾回收
-XX:+UseCMSCompactAtFullCollection :在CMS垃圾收集完成之后,进行一次内存碎片整理
-XX:+CMSFullGCsBeforeCompaction=n :在n次CMS回收后进行一次内存碎片整理
使用CMS回收方法去的perm区,默认情况下,还需要触发一次FullGC
-XX:+CMSClassUnloadingEnabled
XX:UseG1GC 开启G1垃圾收集器
两个重要的参数
-XX:MaxGcPasuseMillis :指定目标最大停顿时间,如果停顿的时间过小,一次收集的区域数量也会变小
就会增加FullGC的可能
-XX:parallelGCThreads :设置并行回收的GC线程数量
-XX:InitiatingHeapOccupancyPercent :设置整个堆使用率达到多少时,触发并发标记的执行,默认是45
-XX:+PrintGC 在程序运行期间,只要遇到GC,就会打印GC情况
占用大小->gc后大小 GC消耗时间
jdk9,jdk10默认使用G1收集器,所以打印GC参数不同
-Xlog:gc
-XX:+PrintGCDetails 打印GC详细信息(JDK8,9,10建议使用-Xlog:gc*)
-XX:+PrintGCTimeStamps 打印分析GC发生的时间
-XX:+PrintGCApplicationConcurrentTime 打印应用程序的执行时间
-XX:+PrintGCApplicationStoppedTime 打印GC产生停顿的时间
-Xloggc:/usr/local/log/gc.log 让gc日志打印在log文件夹下的gc文件中,因为默认情况下gc日志在控制台输出
栈上分配,逃逸分析(方法内的变量被外部引用)
允许对象直接在栈上进行分配,随线程停止而销毁,这样做可以加快分配速度,减少GC次数
栈空间较小,所以不适合大对象的栈上分配
-XX:+DoEscapeAnalysis 启用逃逸分析
-XX:+EliminateAllocations 开启标量替换(默认打开),允许对象打散分配在栈上
比如对象拥有id和name两个字段,那么这两个字段将会被视为两个独立的变量进行分配。
对象晋升
-MaxTenuringThreshold=n ,当对象经历了多少次GC次数后进入老年代
注意:大对象直接晋升到老年代
-PretenureSizeThreshold=n 这里的单位是字节,新生对象大于这个值的时候,会直接分配到老年代
1、对存活对象标注时间过长:比如重载了Object类的Finalize方法,导致标注Final Reference耗时过长;或者String.intern方法使用不当,导致YGC扫描StringTable时间过长。
2、长周期对象积累过多:比如本地缓存使用不当,积累了太多存活对象;或者锁竞争严重导致线程阻塞,局部变量的生命周期变长
当Eden区空间不足时,就会触发YGC。结合新生代对象的内存分配看下详细过程:
1、新对象会先尝试在栈上分配,如果不行则尝试在TLAB分配,否则再看是否满足大对象条件要在老年代分配,最后才考虑在Eden区申请空间。
2、如果Eden区没有合适的空间,则触发YGC。
3、YGC时,对Eden区和From Survivor区的存活对象进行处理,如果满足动态年龄判断的条件或者To Survivor区空间不够则直接进入老年代,如果老年代空间也不够了,则会发生promotion failed,触发老年代的回收。否则将存活对象复制到To Survivor区。
4、此时Eden区和From Survivor区的剩余对象均为垃圾对象,可直接抹掉回收。
此外,老年代如果采用的是CMS回收器,为了减少CMS Remark阶段的耗时,也有可能会触发一次YGC,这里不作展开。
大多数情况下,对象直接在年轻代中的Eden区进行分配,如果Eden区域没有足够的空间,那么就会触发YGC(Minor GC),YGC处理的区域只有新生代。因为大部分对象在短时间内都是可收回掉的,因此YGC后只有极少数的对象能存活下来,而被移动到S0区(采用的是复制算法)。当触发下一次YGC时,会将Eden区和S0区的存活对象移动到S1区,同时清空Eden区和S0区。当再次触发YGC时,这时候处理的区域就变成了Eden区和S1区(即S0和S1进行角色交换)。每经过一次YGC,存活对象的年龄就会加1。
下面4种情况,对象会进入到老年代中:
当晋升到老年代的对象大于了老年代的剩余空间时,就会触发FGC(Major GC),FGC处理的区域同时包括新生代和老年代。除此之外,还有以下4种情况也会触发FGC:
有时候我们需要设定maven环境下的JVM参数,以便通过maven执行的命令或启动的系统能得到它们需要的参数设定。比如:当我们使用jetty:run启动jetty服务器时,在进行热部署时会经常发生:java.lang.OutOfMemoryError: PermGen space问题,这时我们需要增大JVM参数MaxPermSize的值。再者,当我们需要进行远程调试时,也需要设置监听端口。maven配置jvm参数的地方是%M2_HOME%/bin/mvn.bat文件,这是启动Maven的脚本文件,在该文件中你能看到有一行注释为:\x0d\x0a@REM set MAVEN_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\x0d\x0a.通过添加set MAVEN_OPTS可以为maven设定jvm参数了。比如:\x0d\x0a1.建立远程调试,端口为:4000的设定为:\x0d\x0aset MAVEN_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=4000\x0d\x0a注意:suspend最好设定为n.设定上述参数后,在eclipse中新建远程调试,设置端口为4000,这样通过jetty:run启动系统时就可以进行远程调试了。\x0d\x0a2.解决自动热部署时java.lang.OutOfMemoryError: PermGen space问题解决这一问题只需要增大PermGen区,默认为 64m,设置方法为:set MAVEN_OPTS=-XX:MaxPermSize=128M-Xint设置jvm以解释模式运行,所有的字节码将被直接执行,而不会编译成本地码。
-Xbatch
关闭后台代码编译,强制在前台编译,编译完成之后才能进行代码执行;
默认情况下,jvm在后台进行编译,若没有编译完成,则前台运行代码时以解释模式运行。
-Xbootclasspath:bootclasspath
让jvm从指定路径(可以是分号分隔的目录、jar、或者zip)中加载bootclass,用来替换jdk的rt.jar;若非必要,一般不会用到;
-Xbootclasspath/a:path
将指定路径的所有文件追加到默认bootstrap路径中;
-Xbootclasspath/p:path
让jvm优先于bootstrap默认路径加载指定路径的所有文件;
-Xcheck:jni
对JNI函数进行附加check;此时jvm将校验传递给JNI函数参数的合法性,在本地代码中遇到非法数据时,jmv将报一个致命错误而终止;使用该参数后将造成性能下降,请慎用。
-Xfuture
让jvm对类文件执行严格的格式检查(默认jvm不进行严格格式检查),以符合类文件格式规范,推荐开发人员使用该参数。
-Xnoclassgc
关闭针对class的gc功能;因为其阻止内存回收,所以可能会导致OutOfMemoryError错误,慎用;
-Xincgc
开启增量gc(默认为关闭);这有助于减少长时间GC时应用程序出现的停顿;但由于可能和应用程序并发执行,所以会降低CPU对应用的处理能力。
-Xloggc:file
与-verbose:gc功能类似,只是将每次GC事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题。
若与verbose命令同时出现在命令行中,则以-Xloggc为准。
-Xmsn
指定jvm堆的初始大小,默认为物理内存的1/64,最小为1M;可以指定单位,比如k、m,若不指定,则默认为字节。
-Xmxn
指定jvm堆的最大值,默认为物理内存的1/4或者1G,最小为2M;单位与-Xms一致。
-Xprof
跟踪正运行的程序,并将跟踪数据在标准输出输出;适合于开发环境调试。
-Xrs
减少jvm对 *** 作系统信号(signals)的使用,该参数从1.3.1开始有效;
从jdk1.3.0开始,jvm允许程序在关闭之前还可以执行一些代码(比如关闭数据库的连接池),即使jvm被突然终止;
jvm 关闭工具通过监控控制台的相关事件而满足以上的功能;更确切的说,通知在关闭工具执行之前,先注册控制台的控制handler,然后对 CTRL_C_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and
CTRL_SHUTDOWN_EVENT这几类事件直接返回true。
但如果jvm以服务的形式在后台运行(比如servlet引擎),他能接 收CTRL_LOGOFF_EVENT事件,但此时并不需要初始化关闭程序;为了避免类似冲突的再次出现,从jdk1.3.1开始提供-Xrs参数;当此 参数被设置之后,jvm将不接收控制台的控制handler,也就是说他不监控和处理CTRL_C_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, or
CTRL_SHUTDOWN_EVENT事件。
-Xssn
设置单个线程栈的大小,一般默认为512k。
上面这些参数中,比如-Xmsn、-Xmxn……都是我们性能优化中很重要的参数;
-Xprof、-Xloggc:file等都是在没有专业跟踪工具情况下排错的好手;
在上一小节中提到的关于JProfiler的配置中就使用到了-Xbootclasspath/a:path;
非Stable参数
前面我们提到用-XX作为前缀的参数列表在jvm中可能是不健壮的,SUN也不推荐使用,后续可能会在没有通知的情况下就直接取消了;但是由于这些参数中的确有很多是对我们很有用的,比如我们经常会见到的-XX:PermSize、-XX:MaxPermSize等等;
下面我们将就Java HotSpot VM中-XX:的可配置参数列表进行描述;
这些参数可以被松散的聚合成三类:
行为参数(Behavioral Options):用于改变jvm的一些基础行为;
性能调优(Performance Tuning):用于jvm的性能调优;
调试参数(Debugging
Options):一般用于打开跟踪、打印、输出等jvm参数,用于显示jvm更加详细的信息;
由于sun官方文档中对各参数的描述也都非常少(大多只有一句话),而且大多涉及OS层面的东西,很难描述清楚,所以以下是挑选了一些我们开发中可能会用得比较多的配置项,若需要查看所有参数列表,可以点击HotSpot VM Specific
Options.查看原文;
首先来介绍行为参数:
参数及其默认值
描述
-XX:-DisableExplicitGC
禁止调用System.gc();但jvm的gc仍然有效
-XX:+MaxFDLimit
最大化文件描述符的数量限制
-XX:+ScavengeBeforeFullGC
新生代GC优先于Full GC执行
-XX:+UseGCOverheadLimit
在抛出OOM之前限制jvm耗费在GC上的时间比例
-XX:-UseConcMarkSweepGC
对老生代采用并发标记交换算法进行GC
-XX:-UseParallelGC
启用并行GC
-XX:-UseParallelOldGC
对Full GC启用并行,当-XX:-UseParallelGC启用时该项自动启用
-XX:-UseSerialGC
启用串行GC
-XX:+UseThreadPriorities
启用本地线程优先级
上面表格中黑体的三个参数代表着jvm中GC执行的三种方式,即串行、并行、并发;
串行(SerialGC)是jvm的默认GC方式,一般适用于小型应用和单处理器,算法比较简单,GC效率也较高,但可能会给应用带来停顿;
并行(ParallelGC)是指GC运行时,对应用程序运行没有影响,GC和app两者的线程在并发执行,这样可以最大限度不影响app的运行;
并发(ConcMarkSweepGC)是指多个线程并发执行GC,一般适用于多处理器系统中,可以提高GC的效率,但算法复杂,系统消耗较大;
性能调优参数列表:
参数及其默认值
描述
-XX:LargePageSizeInBytes=4m
设置用于Java堆的大页面尺寸
-XX:MaxHeapFreeRatio=70
GC后java堆中空闲量占的最大比例
-XX:MaxNewSize=size
新生成对象能占用内存的最大值
-XX:MaxPermSize=64m
老生代对象能占用内存的最大值
-XX:MinHeapFreeRatio=40
GC后java堆中空闲量占的最小比例
-XX:NewRatio=2
新生代内存容量与老生代内存容量的比例
-XX:NewSize=2.125m
新生代对象生成时占用内存的默认值
-XX:ReservedCodeCacheSize=32m
保留代码占用的内存容量
-XX:ThreadStackSize=512
设置线程栈大小,若为0则使用系统默认值
-XX:+UseLargePages
使用大页面内存
我们在日常性能调优中基本上都会用到以上黑体的这几个属性;
调试参数列表:
参数及其默认值
描述
-XX:-CITime
打印消耗在JIT编译的时间
-XX:ErrorFile=./hs_err_pid.log
保存错误日志或者数据到文件中
-XX:-ExtendedDTraceProbes
开启solaris特有的dtrace探针
-XX:HeapDumpPath=./java_pid.hprof
指定导出堆信息时的路径或文件名
-XX:-HeapDumpOnOutOfMemoryError
当首次遭遇OOM时导出此时堆中相关信息
-XX:
出现致命ERROR之后运行自定义命令
-XX:OnOutOfMemoryError=""
当首次遭遇OOM时执行自定义命令
-XX:-PrintClassHistogram
遇到Ctrl-Break后打印类实例的柱状信息,与jmap -histo功能相同
-XX:-PrintConcurrentLocks
遇到Ctrl-Break后打印并发锁的相关信息,与jstack -l功能相同
-XX:-PrintCommandLineFlags
打印在命令行中出现过的标记
-XX:-PrintCompilation
当一个方法被编译时打印相关信息
-XX:-PrintGC
每次GC时打印相关信息
-XX:-PrintGC Details
每次GC时打印详细信息
-XX:-PrintGCTimeStamps
打印每次GC的时间戳
-XX:-TraceClassLoading
跟踪类的加载信息
-XX:-TraceClassLoadingPreorder
跟踪被引用到的所有类的加载信息
-XX:-TraceClassResolution
跟踪常量池
-XX:-TraceClassUnloading
跟踪类的卸载信息
-XX:-TraceLoaderConstraints
跟踪类加载器约束的相关信息
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)