常用JVM参数

http://blog.csdn.net/gzh0222/article/details/8223277 

分析gc日志后,经常需要调整jvm内存相关参数,常用参数如下

-Xms:初始堆大小,默认为物理内存的1/64(<1GB);默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制

-Xmx:最大堆大小,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制

-Xmn:新生代的内存空间大小,注意:此处的大小是(eden+ 2 survivor space)。与jmap -heap中显示的New gen是不同的。整个堆大小=新生代大小 + 老生代大小 + 永久代大小。 
在保证堆大小不变的情况下,增大新生代后,将会减小老生代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。

-XX:SurvivorRatio:新生代中Eden区域与Survivor区域的容量比值,默认值为8。两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。

-Xss:每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。应根据应用的线程所需内存大小进行适当调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。一般小的应用, 如果栈不是很深, 应该是128k够用的,大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。和threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:"-Xss is translated in a VM flag named ThreadStackSize”一般设置这个值就可以了。

-XX:PermSize:设置永久代(perm gen)初始值。默认值为物理内存的1/64。(jdk8已取消永久代)

-XX:MaxPermSize:设置持久代最大值。物理内存的1/4。(jdk8已取消永久代)

-Xloggc:eclipse_gc.log (设置垃圾回收日志打印的文件,文件名称可以自定义)

-XX:+PrintGCTimeStamps (打印垃圾回收时间信息时的时间格式) 
-XX:+PrintGCDetails (打印垃圾回收详情)

示例:

-Xmx11M -Xms4M -verbose:gc -Xloggc:eclipse_gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

GC日志分析

垃圾收集器在进行垃圾收集的过程中,可以输出日志,我们通过日志,可以看到当前垃圾收集器的运行情况。通过gc日志,我们可以观察垃圾收集器的行为,以及当前应用程序的GC情况和内存使用情况。学会查看和分析垃圾收集日志,一方面可以帮助我们学习垃圾收集器;另一方面,在必要的时候,可以帮助我们定位问题,解决问题,对JVM进行优化。

  默认,JVM不会打印出GC日志信息,可以通过参数-XX:+PrintGC或-verbose:gc来设置JVM输出gc日志到终端中。

  JVM参数:-XX:+PrintGC -XX:+UseSerialGC -Xms10m -Xmx10m

[GC (Allocation Failure)  1922K->1394K(9920K), 0.0021245 secs]
[Full GC (Allocation Failure)  7585K->7538K(9920K), 0.0023668 secs]

  当设置了"-XX:+PrintGC"或者"-verbose:gc"以后就会输出类似输出上面的GC日志。这是最简单的GC日志,包含了垃圾收集过程中的信息。其中红色部分的"GC"和"Full GC"表示这次GC的类型,而绿色部分的"Allocation Failure"表示表示发生这次GC的原因,从上面的日志可以看出,是由于内存分配失败导致的GC。后面的黄色部分"1922K->1394K(9920K)"表示这次GC导致JVM中堆内存的使用量从1922K降低到了1394K,其中括号中表示当前整个JVM堆的大小。最后蓝色部分的"0.0021245 secs"表示这次GC持续的时间。

  上面输出的是简单格式的GC日志,虽然提供了一些信息,但是通过这些信息,我们没法知道这次GC发生的时候,这次GC是发生在老年代还是在年轻代,是否有对象从年轻代被移动到了老年代等信息,所以我们希望可以看到更加详尽的信息。这个时候,我们需要设置-XX:+PrintGCDetails参数来输出更加详细的GC日志,下面我们结合不同的收集器组合,来分析下它们的输出日志。

Serial GC + Serial Old

  Serial GC和Serial Old收集器是比较早的单线程收集器,工作原理我们在上面已经介绍过了。这里,我们来看下使用这两款收集器进行垃圾收集的时候,输出的日志格式是怎么样的。首先我们需要设置JVM参数:

  JVM参数:-XX:+PrintGC -XX:+PrintGCDetails -XX:+UseSerialGC -Xms10m -Xmx10m

[GC (Allocation Failure)
[DefNew: 1922K->319K(3072K), 0.0027356 secs] 1922K->1394K(9920K), 0.0027698 secs]
[Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure)
[Tenured: 6514K->6484K(6848K), 0.0025899 secs] 8562K->8532K(9920K), [Metaspace: 2984K->2984K(1056768K)], 0.0026153 secs]
[Times: user=0.00 sys=0.00, real=0.00 secs] 

  可以发现,通过设置了"-XX:+PrintGCDetails"以后,输出的GC日志信息多了很多。我们先来看第一条,红色部分"GC"表示这次发生的是Minor GC,绿色部分"Allocation Failure"表示导致这次GC的原因是内存分配失败。接下来,黄色部分的内容,则和前面的日志有些区别了,这里输出的内容相对比较详细。"DefNew: 1922K->319K(3072K), 0.0027356 secs] 1922K->1394K(9920K), 0.0027698 secs",其中DefNew表示这次GC发生在年轻代(不同的收集器,日志的格式不一定相同),接下来"1922K->319K"表示这次GC导致年轻代使用的内存从1922K降到319K,括号中的"3072K"表示年轻代中的堆内存大小为3072K。"0.0027356 secs"表示这次年轻代GC耗时0.0027356s。后面的"1922K->1393K"表示总的堆内存(年轻代 + 老年代)的使用情况的变化,从1922K降低到1394K, 括号中的"9920K"表示总的堆内存的大小。最后的"0.0027698 secs"表示这次GC总的消耗的时间。最后是这次GC消耗的时间的统计,其中user表示用户态CPU执行的时间,sys表示内核态CPU执行的时间,这两个时间不包括被挂起消耗的时间,而real表示的是实际的时间,可以认为是墙上时钟走过的时间。

  下面的这条日志,"Full GC"表示这次GC是一次Major GC,后面的原因和上面一样。我们来看下黄色部分,"Tenured"表示这次GC发生在老年代,其中"6524K->6484K"表示老年代内存从6524K降低到6484K。后面的时间"0.0025899 secs"表示这次老年代GC耗时0.0025899s。接下来的"8562K -> 8532K"和上面提到的一样,表示整个堆内存的变化。最后的时间表示这次GC的总耗时为"0.0026153s"。

Parallel Scanvage + Parallel Old

  不同的垃圾收集器,输出的日志信息也不是完全相同的,上面我们看到的日志,是使用Serial GC和Serial Old收集器输出的gc日志,而下面的日志信息,则是使用Parallel Scavenge收集器和Parallel Old收集器输出的日志。

  JVM参数:-XX:+PrintGC -XX:+UseParallelOldGC -XX:+PrintGCDetails -Xms10m -Xmx10m

[GC (Allocation Failure) --
[PSYoungGen: 1391K->1391K(2560K)] 7537K->7537K(9728K), 0.0007436 secs]
[Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure)
[PSYoungGen: 1391K->1374K(2560K)]
[ParOldGen: 6145K->6145K(7168K)] 7537K->7520K(9728K), [Metaspace: 2984K->2984K(1056768K)], 0.0037697 secs]
[Times: user=0.01 sys=0.00, real=0.01 secs] 

  可以看到,使用Parallel Scavenge 和 Parallel Old收集器输出的日志,会有一些不同,不过日志内容大体上差不多。user=0.01代表用户态回收耗时,sys=0.00内核态回收耗时,real=0.01实际耗时。

最后,我们来看下CMS垃圾收集器的日志是怎么样的,相对上面几款收集器,CMS相对更加复杂,从它输出的日志也可以看出来。

ParNew + Concurrent Mark Sweep(CMS)

  下面,我们来看下ParNew配合CMS收集器在进行垃圾收集的时候,输出的GC 日志信息。

  JVM参数:-XX:+PrintGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -Xms10m -Xmx10m

[GC (Allocation Failure) [ParNew: 2418K->0K(3072K), 0.0032236 secs] 3508K->3455K(9920K), 0.0032520 secs]
[Times: user=0.01 sys=0.00, real=0.00 secs] [GC (CMS Initial Mark) [1 CMS-initial-mark: 3455K(6848K)] 4479K(9920K), 0.0005566 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-mark-start]
[CMS-concurrent-mark: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (CMS Final Remark) [YG occupancy: 1024 K (3072 K)]
[Rescan (parallel) , 0.0001118 secs][weak refs processing, 0.0000191 secs][class unloading, 0.0002858 secs]
[scrub symbol table, 0.0003506 secs][scrub string table, 0.0001305 secs]
[1 CMS-remark: 3455K(6848K)] 4479K(9920K), 0.0009500 secs]
[Times: user=0.00 sys=0.00, real=0.01 secs]
[CMS-concurrent-sweep-start]
[CMS-concurrent-sweep: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-reset-start]
[CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

  通过第一条日志,可以看出我们使用"-XX:+UseConcMarkSweepGC"指定CMS垃圾收集器的时候,使用的是ParNew + CMS收集器组合。下面输出的一堆日志,就是CMS收集器在进行垃圾收集过程中输出的信息。可以明显的看到,CMS在进行垃圾收集的过程中,经历了4个阶段,在日志中我用4中颜色标记出来了。需要注意的是黄色部分,这是CMS的重新标记的阶段,在上面我们介绍CMS收集器的时候说过,在这个阶段,是会出现Stop The World的,所以如果这个阶段消耗的时间比较长,则会影响应用的响应时间。

其他日志参数

  有时候,我们需要在GC日志中输出时间值,这样我们就可以知道这次GC发生的具体时间点。我们可以通过JVM参数"-XX:+PrintGCTimeStamps" 和"-XX:+PrintGCDateStamps"来设置日志输出的时间。使用"-XX:+PrintGCTimeStamps"参数,可以在输出的日志前加上产生日志的时间戳:

7.327: [GC (Allocation Failure) 7.327: [DefNew: 2095K->2095K(3072K), 0.0000209 secs]

  可以看到,输出的日志中,在头部包含了一个时间戳,表示从JVM启动以来经过的秒数。而"-XX:+PrintGCDateStamps"则表示输出日志时的当前时间,相对来说更加直观:

2017-02-24T00:14:38.611-0800: [GC (Allocation Failure)
2017-02-24T00:14:38.611-0800: [DefNew: 1922K->319K(3072K), 0.0025676 secs] 1922K->1394K(9920K), 0.0026134 secs] 

  除了将日志输出到控制台,我们还可以将日志输出到日志文件中,这样就可以通过分析日志文件来分析系统的GC情况了,一般在服务器运行过程中,我们都会将GC日志输出到指定的文件中,供需要的时候分析。可以通过JVM参数"-Xloggc:<file>"来指定日志输出的目录。

JVM GC日志分析相关推荐

  1. 【Java 虚拟机原理】垃圾回收算法 ( 设置 JVM 命令参数输出 GC 日志 | GC 日志输出示例 | GC 日志分析 )

    文章目录 一.设置 JVM 命令参数输出 GC 日志 二.GC 日志示例 三.GC 日志分析 一.设置 JVM 命令参数输出 GC 日志 在 IntelliJ IDEA 的启动参数中设置 -XX:+P ...

  2. JVM学习笔记-GC日志分析(对象优先在Eden区分配)

    前言 在进行GC日志分析前,先了解一下JVM虚拟机运行时数据区的主要划分: Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域 有各自的用途,以及创建和销毁 ...

  3. JVM性能优化之GC日志分析

    JVM性能优化之GC日志分析 文章目录 JVM性能优化之GC日志分析 前言 一.GC日志参数 GC日志参数 常用的垃圾收集器配置 大对象回收 二.GC日志分析工具 GCeasy JVM memory ...

  4. JVM:GC日志解读

    深入理解Java虚拟机 [JVM]Java内存区域与垃圾收集 - 思维导图 [JVM]类加载机制 - 思维导图 [JVM]OOM实例分析 [JVM]理解Class文件(1):手动解析常量池 [JVM] ...

  5. GC之七--gc日志分析工具

    性能测试排查定位问题,分析调优过程中,会遇到要分析gc日志,人肉分析gc日志有时比较困难,相关图形化或命令行工具可以有效地帮助辅助分析. Gc日志参数 通过在tomcat启动脚本中添加相关参数生成gc ...

  6. JVM GC日志说明

    本例jvm配置(jdk1.8) -server -Xmx10m -Xms10m -XX:+DoEscapeAnalysis -XX:+PrintGCDetails gc日志 [GC (Allocati ...

  7. java8 GC日志分析

    @[toc] 前言 最近学习分析了一下java8的GC日志,顺便记录下来,忘性太大了 背景: java version "1.8.0_144" Java(TM) SE Runtim ...

  8. 第 17 章 一 G1回收器(重点)、垃圾回收器总结(重要)、GC日志分析、垃圾回收器的新发展(了解)

    由于篇幅, 无缝衔接上篇博客 ! 7.G1 回收器 (重重点):区域化分代式 (并行回收器) JDK9的默认垃圾回收器 7.1.为什么还需要 G1 在延迟可控的情况下, 尽可能获取高的吞吐量 采用标记 ...

  9. ZGC 特性和 GC 日志分析

    ZGC 概述 Z Garbage Collector,也称为ZGC,在 jdk 11 中引入的一种可扩展的低延迟垃圾收集器,在 jdk 15 中发布稳定版.在旨在满足以下目标: < 1ms 最大 ...

最新文章

  1. 编写spring应用
  2. 2017-2018 ACM-ICPC Asia East Continent League Final (ECL-Final) 题解(10 / 13)
  3. oc中在控件上显示图片
  4. 分布式文件系统研究-搭建图片服务虚拟主机
  5. CrudRepository/JpaRepository/PagingAndSortingRepository之间的区别
  6. when is SAP UI5 url hash changed in browser
  7. python中意外缩进是什么意思_如何处理python中的“意外缩进”?
  8. 神马搜索聚焦大数据营销 汇川广告平台 快、准、省
  9. Go 函数的 Map 型参数,会发生扩容后指向不同底层内存的事儿吗?
  10. [转】Ubuntu16.04 字符界面 ifconfig 命令无网络接口 ens33 的解决方法
  11. POJ2488 A Knight's Journey(DFS)
  12. 基于java的生信软件_常用生物信息学软件介绍和文献依据.docx
  13. 新浪微博与腾讯微博的开放平台比较 -- 从程序员的角度
  14. zxr10交换机配置手册vlan_中兴交换机配置命令
  15. ubuntuv20启动界面美化_聊一聊我的win10系统美化/使用习惯
  16. ROS-2Dslam算法比较
  17. 中科院广州电子CASAIM与东风日产在3D打印生产制造发动机检具及治具应用研究项目顺利落地
  18. Spring04:自动装配
  19. 谷氨酰胺主要用途,以及谷氨酰胺测定试剂盒研究
  20. Maven的爱恨情仇

热门文章

  1. 愿光阴含笑,岁月静好
  2. UGC内容审核难点∣网络媒体平台内部审核机制的不健全
  3. c语言指针大括号的用法,c语言大括号的用法
  4. 1个G带你学软件测试项目实战教程:《学车不》APP测试
  5. python智慧树判断题_知到智慧树_Python程序设计基础_判断题答案
  6. 股权(风险)投资全局观和方法论
  7. halcon中怎么降低图像亮度_第6课-调整图像亮度和对比度
  8. quota 详解---quota 是什么
  9. 国家开放大学 《数据库应用技术》形考任务11数据库题
  10. 腾讯云Linux轻量应用服务器一键部署WordPress个人博客教程