JVM垃圾回收——新生代,老年代,永久代,Minor GC,Full GC

参考资料:

  1. 《深入理解Java虚拟机》——周志明
  2. https://blog.csdn.net/u010796790/article/details/52213708
  3. https://blog.csdn.net/lirenzuo/article/details/77749925
  4. https://www.cnblogs.com/ygj0930/p/6522828.html

周志明先生,在《深入理解Java虚拟机》一书中曾提到:程序计数器,虚拟机栈,本地方法栈这3个区域是线程私有的,随线程而生,随线程而灭,这几个区域就不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存就自然跟着回收了。主要讨论Java堆和方法区的回收。(Java堆和方法区是《Java虚拟机规范》的术语)

Java堆通常分为新生代,老年代。永久代,实际上就是方法区。

【方法区】是JVM的一种规范,存放类信息,常量,静态变量,即时编译后的代码等。

【永久代】是HotSpot的一种具体实现,实际上指的就是方法区,或者说用永久代来实现方法区。对于其他虚拟机来说是不存在永久代的概念的。

新生代:

对于新生代而言,无论是使用哪一种垃圾收集器(JDK1.6之前新生代的垃圾收集器有三种:Serial,ParNew,Parallel Scavenge)采用的都是复制收集算法

JDK1.6中,新生代与老年代的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),新生代又可细分为:EdenFrom SurvivorTo Survivor三个区(811),也就是说新生代中可用内存空间为整个新生代容量的90%,有10%的内存被浪费。

Eden:新对象的出生地。
From Survivor上一次GC的幸存者,作为这一次GC的被扫描者。
To Survivor保留MinorGC过程中的幸存者。

MinorGC的触发条件】Eden区内存不足的时候,虚拟机将进行一次MinorGCSurvivor区内存不足不会触发MinorGCMinorGC之后,可能会与一些新生代的对象年龄满足进入老年代,老年代的占用会有所升高。

MinorGC的过程MinorGC采用复制算法。首先,把EdenFrom Survivor区域中存活的对象复制到To Survivor区域,同时把这些对象的年龄+1(默认情况下15岁就直接送到老年代了,晋升老年代的阈值可以通过-XX:MaxTenuringThreshold设置);然后,清空EdenFrom Survivor中的对象;最后,To SurvivorFrom Survivor互换,原To Survivor成为下一次GC时的From Survivor区。

老年代:

主要存放程序中年龄较大和需要占用大量连续内存空间的对象。老年代的对象比较稳定,所以MajorGC/Full GC执行的频率较低。一般都是在空间不足的时候才会执行MajorGC/Full GC。

JDK1.6之前老年代的垃圾收集器Serial Old,Parallel Old采用的是标记—整理算法,CMS采用的标记—清除算法。标记—清除算法会产生大量的内存碎片。

【新生代的对象进入老年代的情况】:

  1. 设置了-XX:PretenureSizeThreshold3M 参数,那么大于3M的对象就会直接就进入老年代,这样做的目的是避免在Eden区以及两个Survivor区之间发生大量的内存复制。(只对于Serial收集器和ParNew两款收集器有效)
  2. 长期存活的对象将进入老年代:对于在Survivor区中每熬过一次Minor GC,年龄就增加1岁,当它的年龄增加到一定程度,就会晋升到老年代中。(默认15岁,可以通过-XX:MaxTenuringThreshold设置)
  3. 如果在Survivor空间中相同年龄所有对象对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold要求的年龄。
  4. 空间分配担保机制:当Minor GC时,新生代存活的对象大于Survivor的大小时,这时一个Survivor装不下它们,那么它们就会进入老年代。

永久代:

HotSpot中对于JVM规范中方法区的实现,指内存的永久保存区域,主要存放Class和Meta(元数据)的信息,Class在被加载的时候被放入永久区域。

在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存

Full GC:

         关于Major GC,如果我们简单理解的话,Major GC和Full GC通常情况下可以认为是等价的。主要是发生在老年代GC,出现Major GC/Full GC,通常情况下伴随着至少一次的Minor GC(并不是绝对的),Major GC/Full GC的速度一般比Minor GC慢10倍以上。

【Full GC的触发条件】:

  1. 当准备要触发一次Minor GC时,如果发现统计数据说之前Minor GC的平均晋升大小比目前老年代剩余的空间大,则不会触发Minor GC而是转为触发Full GC(因为HotSpot VM的GC里,除了CMS的concurrent collection之外,其它能收集老年代的GC都会同时收集整个GC堆,包括新时代,所以不需要事先触发一次单独的Minor GC);
  2. 如果有永久代的话,要在永久代分配空间但已经没有足够空间时,也要触发一次Full GC;(Java虚拟规范中并不要求虚拟机在方法区实现垃圾收集,而且在方法区中进行垃圾收集的“性价比”较低。在大量使用频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出。)
  3. System.gc()、heap dump带GC,默认也是触发Full GC。
  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JVM中的年代垃圾回收是指对年代进行垃圾回收的过程。年代是堆内存的一部分,用于存放生命周期较长的对象。年代垃圾回收的触发条件与空间分配担保有关。在发生Minor GC之前,虚拟机会检查年代最大可用的连续空间是否大于新生代所有对象的总空间。如果大于,则此次Minor GC是安全的;如果小于,则虚拟机会根据HandlePromotionFailure设置值来决定是否进行空间分配担保。 空间分配担保是指在发生Minor GC时,如果年代的连续空间小于新生代所有对象的总空间,虚拟机会根据HandlePromotionFailure的设置值来决定后续的操作。如果HandlePromotionFailure为true,虚拟机会进一步检查年代最大可用连续空间是否大于历次晋升到年代的对象的平均大小。如果大于,则尝试进行一次Minor GC,但仍然有风险;如果小于或者HandlePromotionFailure为false,则会进行一次Full GC。 总结一下,年代垃圾回收是在发生Minor GC时对年代进行的垃圾回收过程。空间分配担保的目的是确保年代有足够的空间来容纳新生代的对象。如果空间不足,根据HandlePromotionFailure的设置值,虚拟机会决定是继续进行Minor GC还是进行一次Full GC。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [JVM垃圾回收——对象进入年代](https://blog.csdn.net/weixin_39555954/article/details/130042958)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值