【深入Java虚拟机】之三:垃圾回收

说明:本文是根据周志明的《深入理解Java虚拟机整理而成》

1. 如何判断对象是否回收

1.1 引用计数算法(主流的Java虚拟机不选它来管理内存)

在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的。

  • 优点:
    引用计数算法(Reference Counting)虽然占用了一些额外的内存空间来进行计数,但它的原理简单,判定效率也很高
  • 缺点:
    有很多例外情况要考虑,必须要配合大量额外处理才能保证正确地工作,譬如单纯的引用计数就很难解决对象之间相互循环引用的问题

1.2 可达性分析算法

基本思路就是通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。
【深入Java虚拟机】之三:垃圾回收_第1张图片

“GC Roots”:

  • 在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。
  • 在方法区中类静态属性引用的对象,譬如Java类的引用类型静态变量。
  • 在方法区中常量引用的对象,譬如字符串常量池(String Table)里的引用。
  • 在本地方法栈中JNI(即通常所说的Native方法)引用的对象。
  • Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器。
  • 所有被同步锁(synchronized关键字)持有的对象。
  • 反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。

1.3 生存还是死亡?

即使在可达性分析算法中判定为不可达的对象,也不是“非死不可”的,这时候它们暂时还处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历两次标记过程:如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记,随后进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。假如对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,那么虚拟机将这两种情况都视为“没有必要执行”。

  • 自救过程:
    如果对象要在finalize()中成功拯救自己——只要重新与引用链上的任何一个对象建立关联即可,譬如把自己(this关键字)赋值给某个类变量要重新与引用链上的任何一个对象建立关联即可,譬如把自己(this关键字)赋值给某个类变量或者对象的成员变量,那在第二次标记时它将被移出“即将回收”的集合;如果对象这时候还没有逃脱,那基本上它就真的要被回收了。

如果引用一直有,那么就不会再被回收了(如果下次还是没有引用,那一定会被回收)

1.4 回收方法区

  • 回收废弃常量与回收Java堆中的对象非常类似。(常量池中其他类(接口)、方法、字段的符号引用也与此类似。)
  • 一个类型是否属于“不再被使用的类”的条件就比较苛刻了。需要同时满足下面三个条件:
  1. 该类所有的实例都已经被回收,也就是Java堆中不存在该类及其任何派生子类的实例。
  2. 加载该类的类加载器已经被回收,这个条件除非是经过精心设计的可替换类加载器的场景,如OSGi、JSP的重加载等,否则通常是很难达成的。
  3. 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

-verbose:class以及-XX:+TraceClass-Loading、-XX:+TraceClassUnLoading查看类加载和卸载信息

2. 垃圾回收算法(追踪式垃圾收集)

说明:

  • 部分收集(Partial GC):指目标不是完整收集整个Java堆的垃圾收集,其中又分为:

    ■ 新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。[ˈmaɪnə®]
    ■ 老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。另外请注意“Major GC”这个说法现在有点混淆,在不同资料上常有不同所指,读者需按上下文区分到底是指老年代的收集还是整堆收集。
    ■ 混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。
    ■ 整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。

你可能感兴趣的:(JVM,jvm)