《深入理解Java虚拟机》读书笔记--第3章 垃圾收集器与内存分配策略

3.1 概述

  1. 垃圾收集器(GC):1.那些内存需要回收;2.什么时候回收;3.如何回收;
  2. 一般 Java 堆 和 方法区

3.2 对象已死吗

  1. 不可能再被任何途径使用的对象
方法 简介
引用计数算法 1.给对象添加一个引用计数器,引用时+1,失效时-1;不能解决对象循环引用
可达性分析算法 1.“GC Roots” 的对象作为起始点,节点向下搜索,路径称为引用链,没有引用链,会被判定可回收
  1. 可达性分析算法,可作为引用链:
    1.虚拟机栈中引用的对象
    2.方法区中类静态属性引用的对象
    3.方法区中常量引用的对象
    4.本地方法栈中JNI引用的对象

3.2.3 再谈引用

分类 简介
强引用 垃圾收集器不会回收掉被引用的对象
软引用 还有用但非必需,系统将要发生内存溢出之前,才会进行回收
弱引用 非必需对象 ,只能生存到下一次垃圾收集器发生之前
虚引用 幽灵引用或幻影引用,目的就是能在这个对象被收集器回收是收到一个系统通知

3.2.4 生存还是死亡

  1. 即使是可达性算法中不可大对象,并非非死不可,真正死亡,要经历两次标记:没有与GC Roots相连接,第一次标记并且进行筛选,条件是是否执行 finalize();当对象没有覆盖 finalize(),或finalize() 已经被虚拟机调用过。当对象被判定有必要执行finalize() ,对象被放置 F-Queue队列中,由Finalizer 线程去执行它,如果没有再 finalize 拯救自己(重新与应用链上任何一个对象建立关系),基本上就会被回收。
  2. finalize() 只能被系统调用一次,可以在 finalize() 中拯救自己,例如 将this 赋值给 成员变量等。

3.2.5 回收方法区

  1. 永久代垃圾收集:废弃常量、无用的类(该类实例全部被回收、加载该类的ClassLoader已经被回收、该类对应的Class对象没有在任何地方被引用)

3.3 垃圾收集算法

分类 简介
标记-清除算法 1.标记处所需要回收的对象,标记完成后统一回收;2.效率问题;3.空间问题,产生大量不连续的内存碎皮
复制算法 1.将内存按容量分成两块,每次只使用一块,当一块用完,将存活对象复制到另一块上,清除使用这块;2.商业采用,一块 Eden 和两块 Survivor ,将 Eden 和 一块Survivor 复制到另一块 Survivor,清理掉 Eden 和 Survivor;3. 当Survivor 不够,需要依赖其他内存(老年代)惊喜分配担保
标记-整理 先标记,让所有存活的对象向一端移动,清除掉端边界以外的内存
分代收集算法 1.Java堆分为新生代(复制算法)和老年代(标记-清除、标记-整理)

3.4 HotSpot 的算法实现

3.4.1 枚举根节点

  1. GC 停顿:GC 进行是,停顿所有 Java 执行线程(Stop-The-World)
  2. 可作为 GC Roots 节点主要在全局性引用(常量、类静态属性)与执行上下文(栈帧中的本地变量表)
  3. OopMap 数据结构存放对象引用信息

3.4.2 安全点

  1. 安全点:是否具有让程序长时间执行的特征为标准选定的,
  2. 长时间执行:特征是指令序列复用,例如方法调用、循环跳转、异常跳转等。
  3. 如何在GC发生手让所有线程(不包括执行调用JNI线程)都“跑”到最近的安全点上停顿下来
    1.抢断式中断
    2.主动式中断:GC需要中断线程时候,不直接对线程操作,仅仅设置一个标志,各个线程执行是主动去轮询这个标志,为真,自己中断挂起,轮询标志的地方和安全点是重合的。

3.4.3 安全区域

  1. 指一段代码片段中,引用关系不会发生改变,在这个区域内任意地方GC都是安全的。

3.5 垃圾收集器

名称 简介
Serial收集器 1.单线程收集器,工作时,会暂停那个所有工作线程;2.简单高效;3.使用Client模式下虚拟机来说是一个很好的选择
ParNew 收集器 1.Serial收集器多线程版本;2.Server模式下的虚拟机首选新生代收集器;3.只要他能与CMS收集器配合工作
Parallel Scavenge 收集器 1.复制算法;2.并发多线程收集器;3.可控制的吞吐量;4.吞吐量优先;5.GC自适应调节策略
Serial Old收集器 1.Serial 老年代收集器;2.单线程收集器;3.标记-整理;4.Client模式下虚拟机使用
Parallel Old 收集器 1.Parallel Scavenge老年代版本;2.多线程和“标记-整理”算法
CMS 收集器 1.获取最短回收停顿时间为目标收集器;2.标记-清除(初始标记、并发标记、重新标记、并发请求);3.并发收集、低停顿;4.对CPU资源敏感、无法处理浮动垃圾、基于标记-清除算法大量碎片空间存在
G1收集器 1.并行与并发;2.分代收集;3.空间整合;4.可预测停顿;5初始标记、并发标记、最终标记、筛选回收

3.6 内存分配与回收策略

  1. 给对象分配内存以及回收分配给对象的内存
  2. 新生代GC(Minor GC)
  3. 老年代GC(Major GC / Full GC)
分配策略 简介
对象优先在Eden分配 1.对象在新生代Eden区中分配,当Eden没哟足够空间,虚拟机放弃一次Minor GC
大对象直接进入老年代 1.需要大量连续内存空间Java对象;2.让大对象在老年代中分配
长期存活对象进入老年代 对象年龄(Age)计数器,默认15岁,进入到老年代
动态对象年龄判定 如果在Survivor空间中所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代

3.6.5 空间分配担保

1.在发生Minor GC 之前,检查老年代最大可用联系空间是否大于新生代所有对象总空间,如果为true,Minor GC 可以确保安全。如果为 false,虚拟机就会查看HandlePromotionFailure设置值是否允许担保失败。 一般为了避免Full GC过于频繁,都是会允许担保失败的。

发布了40 篇原创文章 · 获赞 15 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_44947117/article/details/104133462