阅读 104

JVM 垃圾回收概要以及垃圾判算法

JVM 垃圾回收理论部分

运行时数据区例子

说明对象创建时的消耗

public void newObject() {
    Object obj = new Object();
}
复制代码
  • 生成了2部分的内存区域,
    • obj这个引用变量,因为是方法内的变量,放到JVM Stack里面。
    • 真正Object.class的实例对象,放到Heap里面。
  • 上述的new语句一共消耗12个bytesJVM规定引用占4个bytes(在JVM Stack),而空对象是8个bytes(在Heap)。
  • 方法结束后,对应Stack中的变量马上回收,但是Heap中的对象要等到GC来回收。

JVM 垃圾回收(Garbage Collection)模型

垃圾回收需要分步骤解决一些问题

  • 垃圾判断算法,判断哪些内容是可以回收的。
    • 引用计数算法(Referenc Counting)
    • 根搜索算法(Root Tracing)
  • GC算法,收集垃圾的算法。
    • 标记-清除算法(Mark-Sweep)
    • 标记-整理算法(Mark-Compact)
    • 复制算法(Copying)
    • 分代算法(Generational)
  • 垃圾回收器的实现和选择,GC算法是内存回收的方法论,垃圾收集器就是算法的落地实现。
    • Serial 垃圾收集器
    • ParNew 垃圾收集器
    • Parallel Scavenge 收集器
    • Serial Old 收集器
    • Parallel Old 收集
    • CMS 收集器(重点)
    • G1 收集器(重点)

关于方法区的垃圾收集

方法区垃圾回收

  • Java虚拟机规范表示可以不要求虚拟机在这区实现GC,这区GC的“性价比”一般比较低
  • 在堆中,尤其是在新生代,常规应用进行一次GC一般可以回收70%~95%的空间,而方法区的GC效率远小于此
  • 当前的商业JVM都有实现方法区的GC(HotSpot有实现),要回收两部分内容:
    • 废弃常量与无用类
  • 主要回收两部分内容:废弃常量与无用类类回收需要满足如下3个条件
    • 所有的实例都已经被GC,也就是JVM中存在该Class的任何实例
    • 加载该类的ClassLoader已经被GC
    • 对应的java.lang.Class对象没有在任何地方被引用,如不能在任何地方通过反射访问该类的方法
  • 在大量使用反射、动态代理、CGLib等字节码框架、动态生成JSP以及OSGi这类频繁自定义ClassLoader的场景都需要JVM具备类卸载的支持以保证方法区不会溢出。

垃圾判断算法

引用计数算法(Reference Counting)

  • 给对象添加一个引用计数器,当有一个地方引用它,计数器加1,当引用失效,计数器减1。
  • 任何时刻计数器为0的对象就是不可能再被使用的。
  • 引用计数算法无法解决对象循环引用的问题。 image.png

根搜索算法(GC Roots Tracing)

  • 在实际的生产语言中(Java、C#等),都是使用根搜索算法判定对象是否存活。
  • 算法基本思路就是通过一系列的称为"Roots"的点作为起始进行向下搜索,当一个对象到GC Roots没有任何引用链(Reference Chain)相连,则证明此对象是不可用的。
  • 在Java语言中,GC Roots包括在VM栈(帧中的本地变量)中的引用方法区中的静态引用。
  • JNI(即一般说的Native方法)中的引用。 image.png

文章分类
后端
文章标签