JVM优化总结

Stella981
• 阅读 609

    首先明确java堆分为perm和heap, 本文只讨论heap空间。

JVM优化总结

概念说明


Eden存放新生成的对象, 它内部的对象生命周期不超过1次Minor GC。

S0、S1的S是Survivor的缩写, 它用于存放MinorGC后幸存,又不满足进入Old Generation条件的对象。为什么要有S0和S1?因为这里用的垃圾回收算法是复制算法, 具体可以查看http://my.oschina.net/xiaoqqq/blog/387327

Old Generation一般称作老年代、旧生代, 它里面存放的是生命周期超过MaxTenuringThreshold值得对象和大对象。

Minor GC即新生代GC, 它是jvm回收Eden和S0、S1内存活对象的GC过程, 他的触发条件是Eden内存不够分配新的对象。

Full GC即全局GC, 每次执行Full GC都会暂停所有用户线程,减少Full GC的执行次数是优化很重要的部分。它的触发条件是Minor GC将对象往Old Generation中移动时发现Old Generation空间不足。

参数介绍


在使用单线程回收器、多线程回收器、并行回收、CMS回收器的情况下(7种垃圾收集器除了G1), 通常minor GC要远快于Full GC。这是很明显的,minor GC只回收新生代, 通常都是些生命周期短的小对象, 而Full GC则回收整个heap,包括老年代中一些寿命很长的对象和大对象。

    各个代的大小设置直接决定了minor GC和Full GC的触发时机, 在代大小的优化上, 主要参数包括-Xms、-Xmx、-Xmn、-XX:SurvivorRatio、-XX:MaxTenuringThreshold。

-Xms和-Xmx分别表示堆heap可以使用的最小内存和最大内存, 优化时通常将这两个值设置为相同的值, 以避免JVM不断为他们分配内存空间。
-Xmn表示新生代内存大小, 新生代中Eden、S0、S1三个区域的比例可以通过-XX:SurvivorRatio来设置, 如果-Xmn的值为10M, -XX:SurvivorRatio的值为8, 就说明Eden区域内存块大小为8M, S0、S1分别为1M。(Eden用于存放)
-XX:MaxTenuringThreshold表示新生代对象经历多少次MinorGC后进入老年代,也就是新生代对象生存周期,此参数默认值一般为15, 且只在串行GC时有效。

其他参数到这里查看http://my.oschina.net/xiaoqqq/blog/384808

监控GC

1. JVM启动参数中添加-verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:./gc.log

以下内容为使用jdk7时输出, jdk版本不同, 启动参数不同显示内容会有些差异。

10.160: [GC10.160: [DefNew: 16384K->2048K(18432K), 0.0169596 secs] 16384K->16120K(131072K), 0.0618775 secs] [Times: user=0.02 sys=0.00, real=0.06 secs] 
10.186: [GC10.186: [DefNew: 18432K->2048K(18432K), 0.0167307 secs] 32504K->31731K(131072K), 0.0168543 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
10.206: [GC10.207: [DefNew: 18432K->2047K(18432K), 0.0174237 secs] 48115K->48028K(131072K), 0.0175884 secs] [Times: user=0.03 sys=0.02, real=0.03 secs] 
10.227: [GC10.227: [DefNew: 18431K->2047K(18432K), 0.0157971 secs] 64412K->64398K(131072K), 0.0159248 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
10.246: [GC10.246: [DefNew: 18431K->2048K(18432K), 0.0204069 secs] 80782K->80756K(131072K), 0.0205314 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
10.269: [GC10.269: [DefNew: 18432K->2048K(18432K), 0.0174500 secs] 97140K->97116K(131072K), 0.0175259 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
10.289: [Full GC10.289: [Tenured: 95068K->107060K(112640K), 0.0388235 secs] 107283K->107060K(131072K), [Perm : 2488K->2488K(21248K)], 0.0389029 secs] [Times: user=0.03 sys=0.00, real=0.03 secs] 
15.319: [GC15.319: [DefNew: 16384K->16384K(18432K), 0.0000187 secs]15.319: [Tenured: 107060K->16622K(112640K), 0.0181551 secs] 123444K->16622K(131072K), [Perm : 2488K->2488K(21248K)], 0.0182582 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
Heap
 def new generation   total 18432K, used 656K [0x00000000f2c00000, 0x00000000f4000000, 0x00000000f4000000)
  eden space 16384K,   4% used [0x00000000f2c00000, 0x00000000f2ca4290, 0x00000000f3c00000)
  from space 2048K,   0% used [0x00000000f3c00000, 0x00000000f3c00000, 0x00000000f3e00000)
  to   space 2048K,   0% used [0x00000000f3e00000, 0x00000000f3e00000, 0x00000000f4000000)
 tenured generation   total 112640K, used 16622K [0x00000000f4000000, 0x00000000fae00000, 0x00000000fae00000)
   the space 112640K,  14% used [0x00000000f4000000, 0x00000000f503b948, 0x00000000f503ba00, 0x00000000fae00000)
 compacting perm gen  total 21248K, used 2495K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
   the space 21248K,  11% used [0x00000000fae00000, 0x00000000fb06fc88, 0x00000000fb06fe00, 0x00000000fc2c0000)
No shared spaces configured.

DefNew是垃圾回收期类型, 即serial young collector, 因为这里在启动参数中指定了-XX:+UseSerialGC, 如果不指定则默认使用ParNewGC, 这里的值就是PSYoungGen。

以上日志说明jvm进行了8次垃圾回收, 其中7次MinorGC, 1次FullGC。FullGC行中显示本次全局回收耗时为0.0389029 secs

2. 使用jstat:

jstat -gc -h20 -t 9076 1s > jstat.log

-h20表示每输出20行,打印一次表头,无此参数时只在监控开始打印一次表头
-t表示在每行前面加入JVM时间戳timestamp

9076是进程id
1s表示每隔1秒打印一次监控结果

优化原则

1. 新生代不能太小也不能太大。 太小会导致MinorGC频繁,有些大对象直接进入老年代。 太大会导致老年代减小, 从而导致Full GC频繁。注意: 看本文最开始的图片。

以下为同一段测试程序, 新生代设置的大小不同, gc的情况:

#-Xms130M -Xmx130M -Xmn120M -XX:+UseSerialGC
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT   
           34.4 12288.0 12288.0  0.0    0.0   98304.0  96510.2   10240.0    10240.0   21248.0 2488.3      1    0.047   2      0.109    0.157

#-Xms130M -Xmx130M -Xmn20M -XX:+UseSerialGC
Timestamp        S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT   
           30.8 2048.0 2048.0  0.0    0.0   16384.0    0.0     112640.0   107060.6  21248.0 2488.3      6    0.146   1      0.049    0.195

重点查看YGC(新生代gc次数)、YGCT(新生代gc耗时)、FGC(full gc次数)、FGCT(full gc耗时) 这4列

通常_推荐新生代占heap空间的1/3_。

2. 根据情况, 合理分配Survivor空间。

3. 合理指定新生代对象的生命周期。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
java 内存管理 堆和栈的理解
在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认识Stack和Heap,并通过这些原理认清Java中静态方法和静态属性的问题。一般,JVM的内存分为两部分:Stack和Heap。Heap(堆)是JVM的内存数据区。Heap的管理很复杂,每次分配不定长的内存空间,专门用来保存对象
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
JVM优化
堆内存设置?原理?JVM堆内存分为2块:PermanentSpace和HeapSpace。?Permanent即持久代(PermanentGeneration),主要存放的是Java类定义信息,与垃圾收集器要收集的Java对象关系不大。?Heap{OldNEW{Eden,from,to}},Old即
Stella981 Stella981
3年前
JVM 参数学习
一、JVM1、JVM产生GC的位置Eden(新生代)MinorGC算法(复制)Oldtenure(老年代) Major(Full)GC(整理压缩)算法2、JVM堆(Heap)内存大小参数\Xmn新生代8:1:1比例\Xms设置初始化堆内存大小 \Xmx设置堆内存最大大小 产生java.lang.