好屌好屌的「GC系列」JVM垃圾定位及垃圾回收算法浅析( 二 )


3) 将A区域全部清除(内存全部释放)
好屌好屌的「GC系列」JVM垃圾定位及垃圾回收算法浅析文章插图
4) 之后再分配内存的时候往B区域分配
清除B之后再继续往A区域分配 , 如此往复 , 拷贝来拷贝去 。
以上过程就是拷贝算法 。
该算法适用于存活对象较少的情况 , 只扫描一次 , 效率有所提高并且没有产生内存碎片 。 需要注意的是 , 移动复制对象时须调整对象引用 。
缺点也显而易见 , 得准备两份内存 , 浪费空间 。
3.3 标记压缩对象分配到内存之后 , 需要回收的时候 , 先把没有引用指向的对象标记为垃圾 , 然后把后面存活的对象拷贝到标记的那个地方 , 不仅如此 , 最后凡是有用的对象全部移到前面 , 无论这个内存是没有使用 , 都压缩整理到前面 , 最后剩下的大块空间就全部清理出来了 。
好屌好屌的「GC系列」JVM垃圾定位及垃圾回收算法浅析文章插图
可以看到 , 标记压缩进行回收垃圾之后 , 空间连续 , 没有碎片 。
我们分析一下该算法的实现思路 ,
1)通过GC Roots找到那些有用的不可回收的
2)把不可回收的有用对象往前移动
所以肯定需要扫描两次内存 , 而且还要移动对象 , 第一次扫描先找游泳对象 , 第二次扫描移动对象 。
移动的过程中 , 如果是多线程还要考虑线程同步 , 所以标记压缩算法效率上要低一些 。
该算法的优点在于对象分配不会产生内存减半 , 而且不会产生内存碎片 。
0x04 小结

  1. 没有任何引用指向的对象是垃圾
  2. 找到垃圾的算法有引用计数法(Reference Count)和根可达算法(Root Searching)
  3. 引用计数法无法解决循环引用的问题
  4. GC Roots:线程栈变量、静态变量、常量池、JNI指针
  5. 垃圾回收算法:标记清除(Mark Sweep)、拷贝(Copying)、标记压缩(Mark Compact)
  6. 标记清除算法容易产生内存碎片使内存空间不连续
  7. 拷贝算法没有内存碎片产生但是浪费空间
  8. 标记压缩算法效率虽然有点低但没有内存碎片产生且不浪费内存空间
作者:行百里er链接:来源:掘金著作权归作者所有 。 商业转载请联系作者获得授权 , 非商业转载请注明出处 。