深入理解JVM虚拟机读书笔记(二)

垃圾收集器与内存分配策略

垃圾收集需要完成三件事:

  1. 那些内存需要回收
  2. 什么时候回收
  3. 如何回收

Q1:哪些内存需要回收

GC主要是对内存运行时区域进行回收,而Java的运行时数据区域主要是:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区、运行时常量池、直接内存,而对于像线程私有的程序计数器、Java虚拟机栈、本地方法栈,他们往往可以随着线程的生灭进行着创建和回收的操作,而对于,堆和方法区这种线程间共享的区域,我们并不能明确当一个线程结束后他是否还被别的线程所引用,因此这种不确定性使得堆和方法区成为JVM主要进行回收管理的区域。

Q2:什么时候回收?

理论上来说当一个对象不存在任何引用的时候就可以对其进行回收,因此可以通过引用计数法的方法来判断一个对象什么时候进行回收,即每当一个地方引用这个对象的时候对计数器加1,反之减1,当计数器为0的时候进行回收,但是在Java中存在着一种循环引用的情况,即A引用了B,B引用了A,此时当没有其他地方引用了这两个对象的时候,这两个对象仍旧持有对方的引用,因此引用计数器的方法不适合对这两个对象进行回收。

回到问题本身,什么时候回收即判断对象是否引用。

数据结构中有一个概念叫做有向图,每个对象是一个节点,对象之间的引用关系形成了边,假设一开始这个有向图是连通的,随着引用关系的变更,原本连通的有向图变得不再连通,会形成一个一个子图,而我们可以通过一些规则设定哪里是主图,从而回收掉那些不和主图连通的子图。这就是根可达性分析算法。在这个算法中,我们判断主图的方法是GCRoots,如果这个图包含着GCRoot就是主图,对主图进行一次扫描,不在主图中的就进行GC操作。

通常可作为GCRoots对象包括:

  1. 虚拟机栈中引用的对象
  2. 方法区类静态属性引用对象
  3. 方法区中常量引用对象
  4. 本地方法栈中JNI引用对象
  5. 虚拟机内部引用,比如基本数据类型
  6. 所有被同步锁持有的对象
  7. 反映Java虚拟机内部情况的JMXBean、JVMT1中注册的回调

查看上面的GCRoots对象,我们不难发现,GC Roots通常包括正在使用的栈,以及Java虚拟机自身需要持有和管理的一些对象。
ps:这些对象在正常情况下是可达的,但在特定条件下也可能变得不可达并被回收。

Q3:如何回收?

整个回收过程其实就是JVM进行一次关于对象的扫描,确定哪些对象是不再被引用的,即垃圾对象。扫描过程中,垃圾收集器会从GC Roots(如虚拟机栈、方法区中的静态变量等)出发,遍历对象的引用关系,标记所有可达的对象为存活对象,未被标记的对象则为垃圾对象。

对全部对象进行扫描确实会耗费性能,因此现代JVM采用了分代收集的策略来优化这一过程。

分代理论主要建立在两个假说上

  1. 绝大多数对象都是朝生夕灭的(生命周期很短)。
  2. 熬过多次的垃圾收集的对象更难以消亡。

因此,我们可以将Java堆分为两个区域(新生代、老年代)。

将那些经历的多次回收仍旧没有被回收的对象放到一个区域(老年代),这个区域垃圾回收的频率较低。

将那些短暂的、新创建的放到一个区域(新生代),这个区域的垃圾回收频率较高,且空间比老年代小。新生代下还划分为Eden区、Survivor From区和Survivor To区,

因此我们的回收类型也可以根据两个分区划分三种类型

  1. Minor GC(或Young GC):针对新生代的垃圾收集。由于新生代中对象生命周期短,因此Minor GC通常很频繁,但每次回收的对象数量较少,所以暂停时间(Stop-The-World Time)也较短。
  2. Major GC:有时也称为Old GC,针对老年代的垃圾收集。由于老年代中对象存活时间较长,因此Major GC不频繁,但每次回收的对象数量较多,可能导致较长的暂停时间。
  3. Full GC:对整个Java堆(包括新生代和老年代)进行垃圾收集。Full GC通常是最慢的,因为它需要扫描整个Java堆并回收所有垃圾对象。Full GC通常是由老年代空间不足触发的,也可能是由某些特定的JVM命令或系统事件触发的。

Q4:再来思考整个回收过程,当老年代里引用了新生代的对象怎么办?

但其实如果新生代里的对象被老年代里的对象引用的话这个对象并不会回收,而多次垃圾扫描后,这个对象最终也会放入老年代,这个过程其实可以通过“记忆集”来实现,将这样的对象放入其中来减少扫描的开销。

//TODO

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值