java对象的回收机制

来源:互联网 发布:画房屋平面图软件 编辑:程序博客网 时间:2024/05/22 03:27

内容概述:

  • 我们知道创建对象是通过new关键字创建的,创建完成后的对象存储在堆内存中,java虚拟机能够完成内存的自动回收,那么JVM是在什么情况下回收对象,如何回收对象?
  • 方法区为什么需要回收,它的回收和堆内存的回收又有什么不同?

1. 在什么情况下回收对象(可达性分析算法):

  • JVM是通过可达性分析算法判断对象是否存活的,这个算法的基本思想是:通过一系列被称为”GC Roots”的对象作为起点,向下搜索,搜索所走过的所有路径称为对象的引用链,当一个对象通过引用链无法到达“GC Roots”时,说明该对象是不可用的,是可以回收的(不一定回收)。
    GC Roots说明:在java中,可作为GC Roots的对象包括以下几种:
    • java虚拟机栈帧中的对象。
    • 方法区中的静态属性引用的对象
    • 方法区中常量引用的对象
    • 本地方法栈JNI中引用的对象

2. 如何回收对象(标记算法判定对象生成还是死亡):

  • 在可达性分析之后,如果判断对象通过引用链无法到达“GC Roots”,则认为该对象是可回收的,但是不保证一定会回收这个对象。对象的回收至少需要经过两次标记过程:
    1. 判断对象通过引用链不可达之后,进行第一次标记并且进行一次筛选,筛选的条件是判断对象是否有必要执行finalized()方法。如果对象没有覆盖finalize()方法或者不是虚拟机第一次调用,则判断为没有必要执行finalize()方法。
    2. 如果对象有必要执行finalized()方法,则会将该对象放到一个F-Queue队列中,并且虚拟机会自动创建一个低优先级的Finalizer线程执行。“执行”的含义是虚拟机会去触发Finalizer线程的执行,但是不会等待结果的返回。因为如果finalized()方法执行时间较长或者产生死循环的话,将导致F-Queue中的其他对象永远处于等待状态。甚至导致整个回收系统的奔溃。finalized()方法是对象实现逃脱的唯一一次机会。如果对象没有逃脱,则在JVM进行第二次标记之后会回收该对象。

3. 方法区的回收

方法去处于永久代中,永久代中的回收主要回收两部分的内容:废弃的常量和无用的类。
1. 回收常量:回收常量和回收堆对象是相同的,如果一个常量在在常量池中已经存在,如果在系统中没有一个对象引用常量池中的常量的话,那么这个常量就需要被回收。
2. 回收类:回收类的条件比回收常量的苛刻许多:以下三点为必要不充分条件:

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