对java内存回收机制的一些总结

之前一直对 java 内存回收机制比较模糊,首先是对 java 的代际划分不大清楚,这两天有时间看了些文章,总结了下,其实代际划分死记硬背容易忘掉,融合 java 的回收设计思想比较容易理解和记忆, java 的内存回收设计思想就是按对象被使用的时间价值或者说权重从小到大进行代际划分。

Java为了更有效率利用内存,提升内存回收的效率,把对象按照生命周期分成了三大代际区:

新生代:新生代分成两块,一块是eden,存放刚new出来的对象,另一块是survivor(survivor0,survivor1)区,存放的是内存回收时在eden区还存活的对象,先放在survivor0survivor0满后再放到survivor1,如果survivor1也满了,则把survivor1的数据放置到老生代区,某种程度而言survivor也可以认为是中生代。内存容量上Edensurvivor0survivor1=811eden区满后出现的回收称为Minor GC(小回收)

老生代:存放经历了多次垃圾回收还存活的对象,内存容量下新生代:老生代=12,老生代满后才会触发对老生代的回收,也称为Full GC(全回收),包括回收老生代和新生代的无用对象以及持久代的回收。

持久代:存放的是静态数据,类,代码

内存回收概念的范围:其实java一般而言正常的内存回收主要是指对堆内存的回收,而持久代的数据属于数据区和方法区,并不是堆内存,所以不属于内存自动回收机制的内容。一般所谓的GC概念的范围是指新生代和老生代。但是又有一说,FullGC也会回收持久代。

代际划分的原因:这个应该和java内存回收的算法或者说策略有关,java内存一开始分配给对象们是连续的内存块,随着陆续有对象失去引用,如果采用简单的标记清理的策略,这部分空间变成FREE(可用)内存,FREE的内存空间在内存块中就出现断断续续的排列,这样不利于新对象的内存分配,无法高效利用碎片的内存空间,为了解决这个问题,只能牺牲效率进行内存整理,把可用内存从碎片化整合成连续化,这种整理非常影响效率,而且空间越大,越碎片化,效率也低,如果采用拷贝清理的策略(也就是把幸存的对象拷贝到新的内存中,然后再清空旧内存块,那么需要的内存则要增加接近一倍,内存利用率不高),所以,按代际划分就是为了解决这个问题,按代际划分后,频繁执行的Minor GC采用的是拷贝清理策略,但是按代际划分后Minor GC需要处理的内存空间就比较小,也就是需要拷贝到新内存块的数据量就减少,内存利用率会提高,补上了完全拷贝清理策略的不足,对于老生代而言,执行的是标记清理加碎片整理的策略,由于大部分对象都在Minor GC环节清掉,正在放到老生代的对象比较小,老生代的清理频率会减少,效率提高,也就是搞这么复杂的代际划分就是为最省资源,最高效率地清理掉不用的对象,并解决内存碎片化的问题,否则一大块无代际划分的堆内存用来存放java对象也是可以的。只是这样要么付出内存代价,要么付出时间代价。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值