GC垃圾回收思想
- 垃圾回收是对内存空间的清理,主要是对无引用的对象在堆中的内存空间的释放
- 回收思想的历程
- 引用计数法:对堆中的对象的引用数进行计数,遍历所有对象的引用数,若存在=0的情况,就对该对象进行释放 缺点:当对象之间存在循环引用的情况时,对象该被清理,但引用数却>0,所以这种方法未被应用于任何一种java虚拟机
- tracing算法:从堆栈和静态存储区开始对所有的引用进行遍历,对发现的引用追踪其对象,直到所有的”活“的对象都被找到,未被找到的就是垃圾,这就解决了上面循环引用的弊端
- 清理垃圾 ”标记-清扫“ 方法,对找到的”活“的对象进行标记,对未标记的对象进行 垃圾回收清扫
缺点:由于是只对未”活“的对象进行清扫,所以会产生磁盘碎片 - 重新对对象分配内存空间,方法名 停止-复制
做法:首先是停止程序的运行,(使用标记-清扫)将原堆中活的对象复制到另外一个堆中,在另外一个堆中就会紧凑排列
缺点:效率很低,需要两个堆,而且要在两个堆中来回倒腾,生命周期长的对象会在两个堆之间多次来回复制 - 为解决两个堆的问题,对堆进行分块处理,复制动作发生在几个大块之间
缺点:生命周期长的对象依然需要从一处复制到另一处 - 方法基于对象生命周期长短差异的特点 首先是对堆进行分区,新生代、老年代、永久代
- 新创建的对象首先都出现在新生代中,将这个区再进行分块8:1:1的比例分为 eden和survivor0和survivor1
- 过程:新产生的对象首先都是出现在eden中,当eden中存满时触发minor Gc,使用前面的(标记-清扫、停止-复制)方法,将eden中存活标记的对象复制到survivor0中,将eden清空
- 当survivor0中存满时,此时eden中也有了新的对象,触发minor Gc,将eden和survivo0中的存活的对象复制到survivor1中,然后清空eden和survivor0
- 清除完成后,eden和survivor0都是空的,于是将survivor1与survivor0交换
- 重复前面的步骤,当survivor1中不足以存放eden和survivo0中的对象时,就将存活对象存放在老年代去
- 老年代满的时候就会触发一次 major GC即FULL GC
- 永久代一般是存放的静态文件,如java类和方法等,当JVM发现某些类或者方法未被使用就会被回收,这个区域对 垃圾回收的方式要求不高
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 SimpleMw's Blog!