深入理解java虚拟机第二版(三)垃圾收集器与内存分配策略

判定对象是否可以被回收;可作为GC Roots的对象包括;java引用分类;判断一个常量是否是“无用的类”;垃圾收集算法(标记-清除算法,复制算法,标记-整理算法,分代收集算法);HotSpot的算法实现;

 

1 判定对象是否可以被回收

1.1 引用计数算法

给对象中添加一个引用计时器,每当有一个地方引用它时,计数器就加1,当引用失效时,计数器就减1;任何时刻计数器为0的对象就是不可能再被使用的;引用计数算法(Reference Counting)的实现简单,判断效率也跟高,但是无法解决对象见的循环引用问题,循环引用,会导致对象无法回收。

1.2 可达性分析算法

这个算法的基础思路就是通过一系列的称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(GC Roots 到这个对象不可达)时,则证明此对象是不可用的。

2. 在java语言中,可作为GC Roots的对象包括下面几种:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(一般谁的Native方法)引用的对象

3. java引用分类:

jdk1.2之后,java将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4种,这4种引用强度依次逐渐减弱。

  • 强引用(Strong Reference)指在程序代码之中普遍存在的,类似“Object obj = new Object()”这类的引用
  • 软引用(Soft Reference)用来描述一些还有用但并非必须的对象。
  • 弱引用(Weak Reference)用来描述非必须对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。
  • 虚引用(Phantom Reference)也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。

4.判断一个常量是否是“无用的类”,(同时满足)

  • 该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例。
  • 加载该类的ClassLoader已经被回收。
  • 该类对应的java.lang.Class 对象没有再任何地方被引用,无法在任何地方通过反射访问该类的方法。

5. 垃圾收集算法

5.1、标记-清除算法

​ 如同它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

5.2、复制算法

将可用内存按照容量划分为大小相等的两块,每次只使用其中的一块。当这块的内存用完了,就将还存活着的对象复制到另外块上面,然后再把已经使用的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。

5.3、标记-整理算法

标记-整理(Mark-Compact)算法,标记过程和“标记-清除”算法一样,整理就是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。主要用于老年代的回收

5.4分代收集算法

一般是把java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都有大批对象死去,只有少量存活,就选择复制算法。而老年代对象存活高,没有额外空间对它进行分配担保,就必须使用**“标记-清理”或者“标记-整理”算法**来进行回收。

6.HotSpot的算法实现(ps:有点蒙,后续再深入理解下)

  • 枚举根节点
  • 安全点
  • 安全区域

 

声明:本文是个人学习笔记,内容来自《深入理解Java虚拟机·JVM高级特性与最佳实践》周志明 与网络文章

posted @ 2020-03-21 15:04  夜未眠shm  阅读(134)  评论(0)    收藏  举报