前言 

JVM GC是JVM的内存回收算法,调整JVM GC(Garbage Collection),可以极大的减少由于GC工作,而导致的程序运行中断方面的问题,进而适当的提高Java程序的工作效率。但是调整GC是以个极为复杂的过程,所以我们要了解JVM内存组成,回收算法,对象分配机制。

JVM 堆内存组成

Java堆由Perm区和Heap区组成,Heap区由Old区和New区(也叫Young区)组成,New区由Eden区、From区和To区(Survivor)组成。


Eden区用于存放新生成的对象。Eden中的对象生命不会超过一次Minor GC。

Survivor Space  有两个,存放每次垃圾回收后存活的对象,即图的S0和S1。

Old Generation  Old区,也称老生代,主要存放应用程序中生命周期长的存活对象

JVM初始分配的内存由-Xms指定,JVM最大分配的内存由-Xmx指定。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。

-XX:NewRatio= 参数可以设置Young与Old的大小比例,-server时默认为1:2,如果太小,会使大对象直接分配到old区去,增大major collections的执行的次数,影响性能。
-XX:SurvivorRatio= 参数可以设置Eden与Survivor的比例,默认为1:8,Survivio大了会浪费,如果小了的话,会使一些大对象在做minor gc时,直接从eden区潜逃到old区,让old区的gc频繁。这个参数保持默认就好了,一般情况下,对性能影响不大。

启动后可通过jmap –heap [pid]查看。
由于堆的整体大小是固定的,young generation越大,tenured generation越小,越会增加major collections的执行的次数。所以最佳的选择是由对象的生命周期分布所决定。

New区的Collector

1、  串行GC(Serial Copying)

client模式下的默认GC方式,也可使用-XX:+UseSerialGC指定。

2、  并行回收GC(Parallel Scavenge)
     server模式下的默认GC方式,也可用-XX:+UseParallelGC强制指定。

采用PS时,默认情况下JVM会在运行时动态调整Eden:S0:S1的比例,如果不希望自动调整可以使用-XX:-UseAdaptiveSizePolicy参数,内存分配和回收的算法和串行相同,唯一不同仅在于回收时为多线程。

3、  并行GC(ParNew)

CMS GC时默认采用,也可以采用-XX:+UseParNewGC指定。内存分配、回收和PS相同,不同的仅在于会收拾会配合CMS做些处理。

Old区的几种Collector

1、  串行GC(Serial MSC)

client模式下的默认GC方式,可通过-XX:+UseSerialGC强制指定。每次进行全部回收,进行Compact,非常耗费时间。

2、  并行GC(Parallel MSC)(备注,吞吐量大,但是gc的时候响应很慢)

server模式下的默认GC方式,也可用-XX:+UseParallelGC=强制指定。可以在选项后加等号来制定并行的线程数。

3、  并发GC(CMS)线上环境采用的GC方式,也就是Realese环境的方式。(备注,响应比并行gc快很多,但是牺牲了一定的吞吐量)

使用CMS是为了减少GC执行时的停顿时间,垃圾回收线程和应用线程同时执行,可以使用-XX:+UseConcMarkSweepGC=指定使用,后边接等号指定并发线程数。CMS每次回收只停顿很短的时间,分别在开始的时候(Initial Marking),和中间(Final Marking)的时候,第二次时间略长。具体CMS的过程可以参考相关文档。JStat中将Initial Mark和Remark都统计成了FGC。

CMS一个比较大的问题是碎片和浮动垃圾问题(Floating Gabage)。碎片是由于CMS默认不对内存进行Compact所致,可以通过-XX:+UseCMSCompactAtFullCollection。

总体来讲,Old区的大小较大,垃圾回收算法较费时间,导致较长时间的应用线程停止工作,而且需要进行Compact,所以不应该出现较多Major GC。Major GC的时间常常是Minor GC的几十倍。JVM内存调优的重点,减少Major GC 的次数,因为为Major GC 会暂停程序比较长的时间,如果Major GC 的次数比较多,意味着应用程序的JVM内存参数需要进行调整。

JVM内存分配策略

1. 对象优先在Eden分配

如果Eden区不足分配对象,会做一个minor gc,回收内存,尝试分配对象,如果依然不足分配,才分配到Old区。

2.大对象直接进入老年代

大对象是指需要大量连续内存空间的Java对象,最典型的大对象就是那种很长的字符串及数组,虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代中分配。这样做的目的是避免在Eden区及两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。PretenureSizeThreshold参数只对Serial和ParNew两款收集器有效,

3.长期存活的对象将进入老年代

在经历了多次的Minor GC后仍然存活:在触发了Minor GC后,存活对象被存入Survivor区在经历了多次Minor GC之后,如果仍然存活的话,则该对象被晋升到Old区。
虚拟机既然采用了分代收集的思想来管理内存,那内存回收时就必须能识别哪些对象应当放在新生代,哪些对象应放在老年代中。为了做到这点,虚拟机给每个对象定义了一个对象年龄(Age)计数器。如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并将对象年龄设为1。对象在Survivor区中每熬过一次Minor GC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁)时,就会被晋升到老年代中。对象晋升老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold来设置。

4.动态对象年龄判定

为了能更好地适应不同程序的内存状况,虚拟机并不总是要求对象的年龄必须达到MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。

5.Minor GC后Survivor空间不足就直接放入Old区

6.空间分配担保

在发生Minor GC时,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间大小,如果大于,则改为直接进行一次Full GC。如果小于,则查看HandlePromotionFailure设置是否允许担保失败;如果允许,那只会进行Minor GC;如果不允许,则也要改为进行一次Full GC。大部分情况下都还是会将HandlePromotionFailure开关打开,避免Full GC过于频繁。

JVM GC组合方式

如何监视GC

1.概览监视gc。

jmap -heap [pid] 查看内存分布

jstat -gcutil [pid] 1000 每隔1s输出java进程的gc情况

2.详细监视gc。

在jvm启动参数,加入-verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:./gc.log。

输入示例:

 [GC [ParNew: 11450951K->1014116K(11673600K), 0.8698830 secs] 27569972K->17943420K(37614976K), 0.8699520 secs] [Times: user=11.28 sys=0.82, real=0.86 secs]

表示发生一次minor GC,ParNew是新生代的gc算法,11450951K表示eden区的存活对象的内存总和,1014116K表示回收后的存活对象的内存总和,11673600K是整个eden区的内存总和。0.8699520 secs表示minor gc花费的时间。

27569972K表示整个heap区的存活对象总和,17943420K表示回收后整个heap区的存活对象总和,37614976K表示整个heap区的内存总和。

[Full GC [Tenured: 27569972K->16569972K(27569972K), 180.2368177 secs] 36614976K->27569972K(37614976K), [Perm : 28671K->28635K(28672K)], 0.2371537 secs]

表示发生了一次Full GC,整个JVM都停顿了180多秒,输出说明同上。只是Tenured: 27569972K->16569972K(27569972K)表示的是old区,而上面是eden区。

更多可以参考 阿里分享的ppt sunjdk1.6gc.pptx

JVM1.6 GC详解相关推荐

  1. 第十五章: 菱悦 -垃圾回收GC详解

    第 15章 垃圾回收GC详解 文章目录 第 15章 垃圾回收GC详解 1.System.gc() 的理解 1.1.System.gc() 方法 1.2.不可达对象回收行为 2.内存溢出与内存泄漏 2. ...

  2. GC详解及Minor GC和Full GC触发条件总结

    GC,即就是Java垃圾回收机制.目前主流的JVM(HotSpot)采用的是分代收集算法.与C++不同的是,Java采用的是类似于树形结构的可达性分析法来判断对象是否还存在引用.即:从gcroot开始 ...

  3. GC详解及Minor GC和Full GC触发条件

    GC,即就是Java垃圾回收机制.目前主流的JVM(HotSpot)采用的是分代收集算法.与C++不同的是,Java采用的是类似于树形结构的可达性分析法来判断对象是否还存在引用.即:从gcroot开始 ...

  4. 监听器之jp@gc详解

    一.jp@gc - Actiive Threads Over Time 不同时间活动用户数量展示 下面是一个阶梯加压测试的图标   二.jp@gc - Transactions per Second ...

  5. JVM垃圾回收机制GC详解

    作为 Java 语言最重要的特性之一的自动垃圾回收机制,也是基于 JVM 实现的.那么,自动垃圾回收机制到底是如何实现的呢? 1.GC是干啥的? 进行资源的回收 1.1.对于 C/C++ 而言 对于C ...

  6. GC详解---JVM(三)

    文章目录 如何判断对象可以被回收 引用计数器 可达性分析算法(知道就可以) finalize()方法 垃圾收集算法 标记-清除算法 复制算法 标记-整理算法 分代收集算法 垃圾收集器 Serial S ...

  7. G1 GC详解及设置

    一.概述 G1 GC,全称Garbage-First Garbage Collector,在JDK1.7中引入了G1 GC,从JAVA 9开始,G1 GC是默认的GC算法.通过-XX:+UseG1GC ...

  8. C#.Net 垃圾回收机制GC详解

    [优点] 1.提高软件系统的内聚. 2.降低编程复杂度,使程序员不必分散精力去处理析构. 3.不妨碍设计师进行系统抽象. 4.减少由于内存运用不当产生的Bug. 5.成功的将内存管理工作从程序的编写时 ...

  9. JVM(Java虚拟机)详解(JVM 内存模型、堆、GC、直接内存、性能调优)

    JVM(Java虚拟机) JVM 内存模型 结构图 jdk1.8 结构图(极简) jdk1.8 结构图(简单) JVM(Java虚拟机): 是一个抽象的计算模型. 如同一台真实的机器,它有自己的指令集 ...

最新文章

  1. Javascript权威指南学习笔记一:数据类型
  2. oracle简体版,oracle|Navicat中文网站
  3. java jar 配置文件路径_java jar 配置文件的相对路径问题
  4. Linux系统日常维护命令
  5. 三阶汉诺塔java源代码_如何使用Java实现汉诺塔问题求解
  6. 工业物联网再起云涌,大咖共叙破圈之道
  7. 从头认识java-16.4 nio的读与写(ByteBuffer的使用)
  8. 已知直角三角形的周长,求可以构成三角形的情况
  9. 计算机二级C语言知识点总结
  10. 商城系统演示站 -多用户商城系统
  11. 如何批量将 Word 文档转为 PDF 格式
  12. 小米商城html+css+js全代码
  13. java面试宝典及答案_最新Java面试宝典及答案
  14. diagnosing error in object detectors 浅析
  15. Mac常用的五款思维导图软件,中文版推荐
  16. mysql 查询当月天数
  17. 三种免费的拍照翻译识别文字方法,总有一种适合你!
  18. 3D动作捕捉实施推流虚拟人物角色动画的实时运动捕捉系统
  19. 技术、产品、交流、思考 - 微软技术暨生态大会 2018
  20. Lodop、C-Lodop页面找不到报404错误解决

热门文章

  1. xamarin使用mysql_[开源] .NetCore .NetFramework Xamarin 使用 ORM FreeSql 访问 MySql
  2. mysql join on 索引_连接查询,表关联查询join on,索引,触发器,视图
  3. nodejs-REPL/回调函数/事件循环
  4. 汇编 Irvine32链接库中一些过程函数的使用说明
  5. 【计算理论】计算复杂性 ( 阶段总结 | 计算理论内容概览 | 计算问题的有效性 | 语言与算法模型 | 可计算性与可判定性 | 可判定性与有效性 | 语言分类 ) ★
  6. 【嵌入式开发】 ARM 关闭 MMU ( 存储体系 | I/D-Cache | MMU | CP15 寄存器 | C1 控制寄存器 | C7 寄存器 | 关闭 MMU )
  7. Golang 入门系列(十) mysql数据库的使用
  8. nginx高性能WEB服务器系列之九--nginx运维故障日常解决方案
  9. LUOGU 3089 后缀排序(模板)
  10. 块级格式化上下文(Block Formatting Context)