JVM的垃圾回收机制

JVM的垃圾回收机制

引用计数、标记清除等策略

JVM主要包含的部分

  • 方法区 (Method Area)
  • Java 堆 (Heap)
  • Java 栈 (Stack)
  • 程序计数器 (PC register)
  • 本地方法栈 (NativeMethod Stack)

内存分配

方法区和Java堆中的回收是动态的,我们所说的垃圾回收也是针对这两块。

回收策略一般包含两个步骤,一个是检测垃圾,另外一个是回收垃圾。

检测垃圾

引用计数法

给一个对象添加计数器,每当有个地方引用到,计数器加1,引用失效减1。无法处理循环引用的问题,比如两个均需要的回收的对象A、B。如果A中引用了B,B中又引用了A,则AB均不会被回收。

可达性分析算法

以根对象为起点进行搜索,如果有对象不可达的话,就是垃圾对象,这里的根集一般包含Java栈中引用的对象、方法区常量池中引用的对象,大部分是动态分配的内存。

回收垃圾

  • 标记-回收
    • 标记所有需要返回的对象,然后统一回收。

  • 复制
    在存储空间划分两个相同的区域,每次只使用其中一个区域。垃圾回收时,遍历当前的使用区域,把正在使用中的对象复制到另外一个区域中,此算法每次只处理正在使用的对象,复制成本较小,同时复制成功后还能进行内存碎片的整理。

  • 标记-整理
    此算法结合了标记-清除复制两个算法的特点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,清除未标记对象并且把存活对象”压缩”到堆的其中一块区域,按顺序排放,此算法避免了标记-清除的碎片问题,同时也避免了复制算法的空间问题。

  • 分代收集算法
    这是现代主流虚拟机常用的垃圾收集算法,是基于一个现象: 不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采用不同的收集方式,以便提高回收效率。一般根据存活的时间将对象划分为:年轻代、年老代、持久代。其中持久代主要存放的是类信息,所以与Java对象的回收关系不大,重点在年轻代和年老代。

  • 年轻代:轻代被分为3个部分——Enden区和两个Survivor区(From和to)当Eden区被对象填满时,就会执行Minor GC。并把所有存活下来的对象转移到其中一个survivor区(假设为from区)。Minor GC同样会检查存活下来的对象,并把它们转移到另一个survivor区(假设为to区)。这样在一段时间内,总会有一个空的survivor区。经过多次GC周期后,仍然存活下来的对象会被转移到年老代内存空间。通常这是在年轻代有资格提升到年老代前通过设定年龄阈值来完成的。需要注意,Survivor的两个区是对称的,没先后关系,from和to是相对的。
  • 年老代:在年轻代中经历了N次回收后仍然没有被清除的对象,就会被放到年老代中,可以说他们都是久经沙场而不亡的一代,都是生命周期较长的对象。对于年老代和永久代,就不能再采用像年轻代中那样搬移腾挪的回收算法
  • 持久代:用于存放静态文件,比如Java类、方法等。持久代对垃圾回收没有显著印象

参考

https://github.com/LiuLei0571/share_doucument/blob
https://www.jianshu.com/p/76dfcadb76a7

猜你喜欢

转载自blog.csdn.net/ethanco/article/details/79983358