聊聊JVM(二)说说GC的一些常见概念

转自CSDN

上一篇总结GC的基础算法,各种GC收集器的基本原理,还是比较粗粒度的概念。这篇会整理一些GC的常见概念,理解了这些概念,相信对GC有更加深入的理解

1. 什么时候会触发Minor GC?

  • Eden区域满了,或者新创建的对象大小 > Eden所剩空间
  • CMS设置了CMSScavengeBeforeRemark参数,这样在CMS的Remark之前会先做一次Minor GC来清理新生代,加速之后的Remark的速度。这样整体的stop-the world时间反而断
  • Full GC的时候会先触发Minor GC

2. 什么时候会触发Full GC?

  • Minor GC后存活的对象晋升到老年代时由于悲观策略的原因,有两种情况会触发Full GC, 1种是之前每次晋升的对象的平均大小 > 老年代剩余空间
  • 1种是Minor GC后存活的对象超过了老年代剩余空间。这两种情况都是因为老年代会为新生代对象的晋升提供担保,而每次晋升的对象的大小是无法预测的,所以只能基于统计,1个是基于历史平均水平,一个是基于下一次可能要晋升的最大水平。这两种情况都是属于promotion failure
  • CMS失败,发生concurrent mode failure会引起Full GC,这种情况下会使用Serial Old收集器,是单线程的,对GC的影响很大。concurrent mode failure产生的原因是老年代剩余的空间不够,导致了和gc线程并发执行的用户线程创建的大对象(由PretenureSizeThreshold控制新生代直接晋升老年代的对象size阀值)不能进入到老年代,只要stop the world来暂停用户线程,执行GC清理。可以通过设置CMSInitiatingOccupancyFraction预留合适的CMS执行时剩余的空间
  • 新生代直接晋升到老年代的大对象超过了老年代的剩余空间,引发Full GC。注意于promotion failure的区别,promotion failure指的是Minor GC后发生的担保失败
  • Perm永久代空间不足会触发Full GC,可以让CMS清理永久代的空间。设置CMSClassUnloadingEnabled即可
  • System.gc()引起的Full GC,可以设置DisableExplicitGC来禁止调用System.gc引发Full GC

3. CMS不等于Full GC,很多人会认为CMS肯定会引发Minor GC。CMS是针对老年代的GC策略,原则上它不会去清理新生代,只有设置CMSScavengeBeforeRemark优化时,或者是concurrent mode failure的时候才会去做Minor GC

4. 什么情况下新生代对象会晋升到老年代?

  • 当对象大小超过了PretenureSizeThreshold设置的对象大小阀值时,对象直接在老年代分配空间
  • 当age从1开始的对象大小累计超过了Survivor区域的1/2(TargetSurvivorRatio所定义)时,会计算一个Thenuring Threshold,超过这个年龄的新生代对象会进入到老年代,即使这时候新生代还有很多的空间。注意MaxTenuringThreshold只是设置了最大的Thenuring Threshold,不是说只有大于Max Tenuring Threshold才会进入到老年代,而是只要超过了计算出来的Tenuring Threshold就会进入老年代,MaxTenuringThreshold规定了Tenuring Threshold的最大值而已。Tenuring Threshold这个值在每一轮GC后都会动态计算,它与TargetSurvivorRatio以及Survivor区的大小有关系,TargetSurivivor默认是50即Survivor的1/2, 会计算出一个Desired Survivor Size,当age从1开始的对象大小累计超过了这个Desired Survivor Size,那么这个age就是Tenuring Threshold的值

5. 一旦对象进入了老年代,那么只有触发CMS(只针对CMS而言)或者Full GC的时候才能被清除

6. Heap什么时候会发生OOM?

  • 当花在GC的时间超过了GCTimeLimit,这个值默认是98%
  • 当GC后的容量小于GCHeapFreeLimit,这个值默认是2%

7. 什么是剩余空间不够?

剩余空间不够不是说整体的空间不够分配某个对象,而是说连续的空间不够分配给某个对象。所以一旦内存碎片大多就可能发生剩余空间不够的问题,所以CMS这种收集器,需要在标记-清除几次之后进行压缩,进行优化。CMSFullGCsBeforeCompaction可以设置进行几次清除之后进行压缩

8. Full GC的次数说的是stop the world的次数,所以一次CMS至少会让Full GC的次数+2,因为CMS Initial mark和remark都会stop the world,记做2次。而CMS可能失败再引发一次Full GC

9. JMI默认会一个小时调用一次System.gc()清理缓存,所以可以DisableExplicitGC,也可以设置sun.rmi.dgc.client.gcInterval和sun.rmi.dgc.server.gcInterval参数来规定JMI清理的时间

10. 对于性能调优来说,应该理解对于给定的硬件,给定的算法(垃圾收集器),单个/多个线程单位时间内能够回收的空间是接近一个常量的。如果想要缩短GC的时候,就要考虑是否要相应调小空间

11. CMS收集器会了减少stop the world的时间,让GC线程和业务线程并发,这样也就相对拉长了CMS收集器单次GC的时间

12. 尽可能地让对象停留在新生代,因为新生代采用了复制算法,相对收回得更快,而且Minor GC的次数肯定比Full GC多,那么对象在新生代被清除的更能性会更高。而对象一旦进入到老年代,那么只有Full GC时才会回收,对象在整个系统停留的时间就会很长,很可能创建的它的线程早就死了,而它还活着

13. 为了尽可能让对象停留在新生代,就要注意设置Survivor区域的大小,因为它直接和对象是否进入老年代相关。之前就遇到过这种情况,明明新生代还有很大的空间,但是每次Minor GC后总是有对象进入到了老年代。后来发现由于Survivor太小,导致Tenuring Threshold为1,意思是年龄为1的对象大小超过了Survivor / 2(可通过TargetSurvivorRatio来调节,默认是50,即1/2),年龄只要超过1的对象这时候就要直接进入老年代了。而进入老年代,对象就只有在Full GC的时候才会被清除。而如果调大了Survivor空间,让对象对象尽量接近Max Tenuring Threshold时才进入到老年代,这时候会大大减少老年代的对象大小,并且让对象在新生代停留时间变长,提高了它们被快速清理出系统的概率。

时间: 2024-12-07 13:35:11

聊聊JVM(二)说说GC的一些常见概念的相关文章

聊聊JVM(四)深入理解Major GC, Full GC, CMS

很多人都分不清Major GC, Full GC的概念,事实上我查了下资料,也没有查到非常精确的Major GC和Full GC的概念定义.分不清这两个概念可能就会对这个问题疑惑:Full GC会引起Minor GC吗? 经过一系列的查找和对JVM表现的分析,基本可以给Full GC和Major GC下一个定义了,这篇说一说概念和理由. 这篇文章Major GCs – Separating Myth from Reality 基本讨论的也是这个问题,但是它没有给出实际的证明. 我们可以认为Maj

简单谈谈JVM中的GC(中)

书接上文,在了解JVM的分代模型后,接着来简单聊聊JVM中GC算法和不同的GC收集器[求关注] GC回收算法 一个GC回收算法通常会做这么几件事: 1.遍历内存,找到被引用的对象 2.清理掉这些未被标记对象的内存 3.被清理掉的内存放回内存中,供其他地方使用 上文也提及过,目前JVM中的搜索引用对象是用的根搜索方式,再重复引用下: 所有的Java对象构成一颗近似"搜索树"的结构,有一个root根节点,每次从root出发向下搜索,当整个树遍历完成后,那些不在其中的变量则视为"垃

JVM内存管理&GC

一.JVM内存划分 |--------------------|-------------PC寄存器-------| |----方法区 ---------|--------------java 虚拟机栈--| |----堆区----------- |-------------本地方法栈------| |----共享区域------- |--------------线程独有-------| 其中左边为共享内存空间,右边为线程独有的线程级别的内存 各个区存储什么? 1.方法区:类的描述,常量等 2.

聊聊JVM的年轻代

聊聊JVM的年轻代 1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描.而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当GC的时候先把这块存"朝生夕死"对象的区域进行回收,这样就会腾出很大的空间出来. 2.年轻代中的GC     HotSpot JVM把年

jvm系列:Java GC 分析

Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢.这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制.概括地说,该机制对JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定

JVM学习之GC常用算法

出处:博客园左潇龙的技术博客--http://www.cnblogs.com/zuoxiaolong,多谢分享 GC策略解决了哪些问题? 既然是要进行自动GC,那必然会有相应的策略,而这些策略解决了哪些问题呢,粗略的来说,主要有以下几点. 1.哪些对象可以被回收. 2.何时回收这些对象. 3.采用什么样的方式回收. GC策略采用的何种算法 有关上面所提到的三个问题,其实最主要的一个问题就是第一个,也就是哪些对象才是可以回收的,有一种比较简单直观的办法,它的效率较高,被称作引用计数算法,其原理是:

总结二:Linux系统的常见发行版(发行商)

总结二:Linux系统的常见发行版(发行商) 三大分支: 1.Slackware Slackware Linux是由Patrick Volkerding开发的GNU/Linux发行版.与很多其他的发行版不同,它坚持KISS(Keep It Simple Stupid)的原则. 比较著名分支发行版: S.u.s.E SUSE(发音 /sus/).SUSE Linux 原来是德国的 SuSE Linux AG公司发行维护的Linux发行版,是属于此公司的注册商标.第一个版本出现在1994年年初.20

JVM——成为Java GC专家(1)

原文: Understanding Java Garbage Collection JVM--成为Java GC专家(1) 理解Java垃圾回收机制(GarbageCollection,简称GC)是如何工作的有什么好处?做为一名软件工程师,为了满足自己的好奇心去了解他是其中的一个原因,并且理解GC工作原理更能让我们写出性能更好.更健壮的Java应用程序. 这仅仅是我个人观念,但是我相信.精通GC是做为一个优秀的Java工程师的必要条件.如果你对GC工作原理感兴趣.那么就意味着你已经具有了开发一定

聊聊returner(二)

关于returner的基础使用请参考returner文章. 继续上面的话题,这里编写c/s端来采集数据. 继续下面话题之前,你需要了解event.returner.zmq协议框架. 步骤: 1.在syndic上运行客户端程序,用来收集数据,其实就是master-minion架构. 2.收集的数据首先写入本地log中,其次发送到顶级master端. 3.顶级master运行服务端程序,用来接收数据,并写入本地数据库. 4.确保数据不丢失,采用zmq协议框架,使用REQ/REP套接字. 先说说客户端