深入理解JVM第三章 垃圾收集器与内存分配策略 笔记

如何判断对象是否存活?

  • 引用计数算法:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,当引用失效时,计数器减1,计数器值为0的对象则判定死亡。优点:简单易实现;缺点:很难解决循环引用等问题。
  • 可达性分析算法:通过一系列的称为 GC Root的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Root没有任何引用链相连时,则证明此对象是不可用的。

可作为GC Roots的对象包括下面几种:

  1. 虚拟机栈(栈帧中本地变量表)中引用的对象

  2. 方法区中类静态属性引用的对象

  3. 方法区中常量引用的对象

  4. 本地方法栈中JNI引用的对象

  • 引用分类:

  1. 强引用

  2. 软引用:系统将要发生内存溢出之前,将会把这些对象列进回收范围之中进行第二次回收。SoftReference类来实现

  3. 弱引用:被弱引用关联的对象只能生存到下一次垃圾收集发生之前。WeakReference

  4. 虚引用:一个对象无论是否有虚引用存在,都会被收集器回收。使用它的唯一目的就是能在这个对象被回收时收到一个通知。

  • 内存回收:当一个对象到GC Roots没有任何链接的时候,这个对象将会被标记且会被做一次筛选,如果这个对象重写了finalize()方法且这个方法没有被执行过,那么会将其放入F-QUEUE中,由JVM创建一个优先级最低的线程finalizer来执行这个队列。在这个方法中如果对象重新与GC Roots建立了链接,则这个对象就不会被回收。

  • 回收方法区的类时需要同时满足以下条件:

  1. 这个类的所有实例已经被回收

  2. 这个类的类加载器已经被回收

  3. 该类的java.lang.Class没有任何地方被引用。

垃圾收集算法:

  • 标记-清理:标记所有需要回收的对象,然后清理内存。有以下缺点
  1. 标记清理的效率都不高
  2. 会产生内存碎片
  • 复制算法:将内存划分为大小相等的两块,每次只使用一块,当进行回收时,将存活的对象复制到另一块对象上去,然后将这块内存全部清理掉,这种方式不会产生内存碎片。一般商用虚拟机都采用这个算法清理新生代的内存,但是因为新生代的对象存活率比较低,一般会将新生代内存划分为Eden和两块较小的survivor内存它们大小比例为8:1:1,对象会在eden和一块survivor上分配内存,当回收时将存活的对象一次性拷贝到另一块survivor然后清理eden和survivor,当另一块survivor空间不够时,则由老年代作为内存担保。
  • 标记-整理:标记需要回收的内存,移动存活的对象到一端,然后清理边界以外的内存。这个算法主要针对存活率比较高的老年代。

HotSpot的算法实现:

  • 枚举根节点:在JIT编译过程中通过OopMap记录引用位置。
  • 安全点
  • 安全区域

垃圾收集器

  • serial收集器:单线程新生代收集器
  • ParNew收集器:新生代并行多线程收集器,相当于serial的多线程版,除了serial只有ParNew能与CMS配合使用。
  • Parallel Scavenge收集器:新生代并行的多线程收集器,它的关注点在于达到一个可控制的吞吐量,吞吐量是指:运行用户代码时间/(运行用户代码时间+垃圾收集时间)。
  • Serial Old收集器:是serial收集器的老年版本,是一个使用标记-整理算法的单线程收集器。一般作为CMS收集器的后备预案。
  • Parallel Old 收集器:使用标记-整理算法的并行收集器
  • CMS收集器:使用标记-清除算法的老年代收集器
  1. 初始标记:标记以下GC Roots能直接关联到的对象,速度很快,需要Stop the world
  2. 并发标记:进行GC Roots Tracing过程,不需要Stop The World
  3. 重新标记:修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分,很快。需要Stop The World
  4. 并发清除
  • G1收集器:
  1. 初始标记
  2. 并发标记
  3. 最终标记
  4. 筛选标记

内存分配策略

  • 对象优先在Eden分配:多数情况下对象在Eden区中分配,当Eden区没有足够的空间进行分配时,虚拟机将进行一次Minor GC,如果Eden和Survivor都没有足够空间存放,则会将新生代中的对象提前转入老年代。
  • 大对象直接进入老年代:为了避免Eden和Survivor之间发生大量内存复制,可以设置-XX:PretenureSizeThreshold参数,控制对象直接进入老年代。
  • 长期存活的对象进入老年代:对象在Eden区经过一次Minor GC被以动到Survivor空间中,对象的年龄设为1,对象在Survivor区中每经过一次Minor GC,年龄就增加1岁,年龄增加到15或者等于-XX:MaxTenuringThreshold参数时进入老年代。
  • 动态对象年龄判定:如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代。
  • 空间分配担保:发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代对象总大小或者历次晋升的平均大小就会进行Minor GC,否则将进行Full GC。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值