首页 - 技术 - Java虚拟机对象生存算法

Java虚拟机对象生存算法

2023-10-04 13:34
-->

1。引用计数算法

  描述:为对象添加引用计数器。每当有对它的引用时,计数器值就加 1;当引用到期时,计数器值减1;任何时候计数器值为 0 的对象是不可能的。重复使用。

  特点:实现简单,判断效率高。

  缺点:无法解决对象之间相互循环引用的问题。

2。可达性分析算法

  描述:通过一系列成为“GC Roots”的对象为参考起点,从这些节点向下搜索。搜索所经过的路径称为参考链。当一个对象没有任何GC Roots的引用链连接起来时,就证明这个对象不可用。

  可用作 GC Root 的对象有:

  • 虚拟机堆栈中引用的对象(堆栈帧中的局部变量表);
  • 方法区静态属性引用的对象。
  • 方法区常量引用的对象。
  • 本地方法栈中JIN(一般说Native方法)引用的对象。

3.引用

  • 强引用:指程序代码中常见的引用,如“Object obj = new Object()”。只要强引用仍然存在,垃圾收集器就永远不会回收所引用的对象。
  • Soft Reference:指一些有用但不必要的对象。对于软引用关联的对象,在系统发生内存溢出异常之前,这些对象会被纳入回收范围进行第二次回收。如果没有足够的内存用于二次垃圾回收,则会抛出内存溢出异常。
  • 弱引用:描述非本质对象,但强度比软引用弱。与弱引用关联的对象只能存活到下一次垃圾回收。当垃圾收集器工作时,无论当前内存是否足够,与弱引用关联的对象都会被回收。
  • 幻像参考:最弱的参考关系。对象是否具有虚引用根本不会影响其生存时间,并且无法通过虚引用获取对象实例。为对象设置虚拟引用关联的唯一目的是当对象被收集器回收时接收系统通知。

4。目标已死

  一个对象要真正宣告死亡,至少需要经过两次标记过程:如果经过可达性分析后发现该对象没有连接到GC Roots的引用链,则会进行第一次标记并过滤一次。过滤条件是这个对象是否需要执行finalize()方法。 (当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,这两种情况被虚拟机视为“不需要执行”)

  如果对象需要执行finalize()方法,那么该对象会被放入一个名为F-Queue的队列中,稍后由虚拟机自动创建的一个低优先级的Finalizer线程来执行它(这里的执行是指触发队列中对象的finalize()方法)。 Finalize()方法是对象逃脱死亡命运的最后机会。随后,GC会对F-Queue队列中的对象进行第二次小规模的标记。如果第二个标记还没有找到有GC Roots的引用链,那么基本上就会被回收。

  如何重新生成F-Queue队列中的对象:只需与引用链上的任意对象重新建立关联即可。例如,将自己(this关键字)复制到类变量或对象的成员变量中。

5。方法区回收

  Java虚拟机规范并不要求虚拟机方法区进行垃圾回收,而方法区垃圾回收的“性价比”普遍较低。

  方法区垃圾回收主要回收两部分:无用常量和无用类;

  如果一个常量没有地方使用,那么可以回收该常量(常量池中其他类/接口、方法、字段的符号引用类似)。

  可回收的类需要满足以下三个条件:

    ----该类的所有对象实例都已被回收,即Java堆中已经没有该类的实例了。

    ----加载该类的ClassLoader已被回收。

    ----该类对应的java.lang.Class对象没有在任何地方被引用,任何地方都无法通过反射访问该类的方法。

  满足以上三个条件的类才可以被回收。它们与物体不同。如果不再使用,则必须将其回收。是否可以在虚拟机中回收可以通过一系列参数来控制。

   在反射、动态代理、CGLib等ByteCode框架大量使用的场景下,动态生成的JSP以及OSGi等频繁定制的ClassLoader都需要虚拟机具备类卸载功能,以保证永久代不溢出。

-->