七、JVM配置参数
一、jvm配置参数分为3大类:
1、跟踪参数:跟踪、监控JVM状态,用于程序员JVM调优及故障排查
2、堆分配参数:分配堆内存
3、栈分配参数:分配栈内存
二、各类配置参数常用参数:
1、常用跟踪监控参数:
①打印gc简要信息
第一个:-XX:+PrintGC
第二个:-verbose:gc
这2个参数效果一样,都是在发生gc时,打印gc简要信息的。以
1:[GC (Allocation Failure) 32686K->1648K(123904K), 0.0007230 secs]2:[GC (Allocation Failure) 34034K->1600K(123904K), 0.0009652 secs]
这个查看结果为例,解释如下:
解释1:总共发生了2次gc,因为打印出的信息标记出了1与2
解释2:以第1次gc为例,32686K表示回收前,对象占用的空间。1648K表示回收后,对象占用的空间。123904K表示还有多少空间可用。0.0007230 secs表示这次垃圾回收花费的时间。
②打印gc详细信息及堆使用详细信息:-XX:+PrintGCDetails
解释1:堆分为新生代、老年代、元空间。
解释2:新生代中又分为伊甸区(eden)和幸存区(from和to)。
解释3:细心的同学可能会发现一种类似于这样的情况:
eden+from+to=65536K+5120K+5120K=75776 并不等于总大小70656K,这是为什么呢?这是因为新生代的垃圾回收算法是采用复制算法,简单的说,就是在from和to之间来回复制(复制过程中再把不可达的对象回收掉),所以必须保证其中一个区是空的,这样才能有预留空间存放复制过来的数据,所以新生代的总大小其实等于eden+from或eden+to=65536K+5120K=70656k。
③将gc日志记录到外部文件中去:-Xloggc:log/gc.log(参数中gc.log就是外部文件的名称)
当java程序出现OOM异常时,总是想查看当时gc的情况,那么使用这个参数记录下gc日志会非常便于故障排查。也可以进行日常JVM监控。
④监控类的加载情况:-XX:+TraceClassLoading
使用这个参数可以监控java程序加载的类。
2、常用堆分配参数
①最大堆:-Xmx,java程序最大能使用多少内存大小,如果超过这个大小,那么java程序会报:out of memory(OOM错误)
②最小堆:-Xms
③指定新生代的内存:-Xmn
④总的堆:目前程序已经配置到的内存大小。一般而言程序一启动,会按照-Xms5m先分配5M的空间,这时总的堆大小就是5M。
⑤空闲堆:程序已经分配的内存大小减去已经使用的内存大小
⑥新生代(eden+from+to)和老年代(不包含永久区)的比值:-XX:NewRatio
Survivor区与Eden区的比值:-XX:SurvivorRatio
这2个比值的计算规则如下:
若**-XX:NewRatio=4,则表示新生代:老年代=1:4**,那么新生代(eden+from+to)=3072+512+512=4096k,老年代=16384k,新生代:老年代=4096k:16384k=1:4。
若**-XX:SurvivorRatio=6,则表示Survivor区:Eden区=2:6**,那么Survivor区(from+to)=1024+1024=2048,Eden区=6144,Survivor区:Eden区=2048:6144=2:6,这样的话,一个幸存区占整个新生代区的1:(2+6)=1/8
⑦官方推荐:
新生代占堆的3/8
幸存代占新生代的1/10
⑧发生OOM异常时把堆栈信息打印到外部文件
第1个:-XX:+HeapDumpOnOutOfMemoryError
第2个:-XX:+HeapDumpPath
⑨将堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展。因为JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指 定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。
3、常用栈分配参数
①栈大小参数为-Xss
栈大小通常只有几百k,决定于函数调用的深度。每个线程都有自己独立的栈空间(私有栈空间,不共享)。如果函数调用太深,超过了栈的大小,则会抛出java.lang.StackOverflowError。遇到这种错误,通常情况下,不是去调整-Xss参数,而是应该去检查是否是函数调用太深导致的,是否使用了递归,能不能保证递归出口等。
三、这些参数在哪里配置?
参数配置好了后,在发生内存溢出异常时(OOM),在console控制台就会按照设置的参数显示信息。
四、如何解决这些OOM异常?
1、要解决OOM异常或heap space的异常,一般的手段是首先通过内存映像分析工具(如Eclipse Memory Analyzer)对dump出来的堆转储快照进行分析,重点是确认内存中的对象是否是必要的,也就是要先分清楚到底是出现了内存泄漏(Memory Leak)还是内存溢出(Memory Overflow)。
2、如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链。于是就能找到泄漏对象是通过怎样的路径与GC Roots相关联并导致垃圾收集器无法自动回收它们的。掌握了泄漏对象的类型信息,以及GC Roots引用链的信息,就可以比较准确地定位出泄漏代码的位置。
3、如果不存在内存泄漏,换句话说就是内存中的对象确实都还必须存活着,那就应当检查虚拟机的堆参数(-Xmx与-Xms),与机器物理内存对比看是否还可以调大,从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况,尝试减少程序运行期的内存消耗。