JVM垃圾回收

如何判定垃圾对象:

  • 引用计数法
    • 为每一个对象添加一个引用计数器,当有地方对该对象有引用的时候,引用计数器+1,当引用失效的时候,引用计数器-1
    • 直到引用计数为0,该对象就变为了无用的对象
    • 优点:算法简单,效率高
    • 缺点:不能解决循环引用的垃圾对象的情况
    • 打印GC收集的日志配置参数:-verbose:gc -XX:+PrintGCDetails
  • 可达性分析法
    • 把程序在堆中创建的对象看作一张图,以栈中GC Root为跟,向下寻找引用对象,如果每一个对象都直接或间接的和GC Root有关联,则不是垃圾对象;如果寻找完毕之后,和GC Root没有关系的对象,即为垃圾对象
    • HotSpot VM采用的就是这种分析算法,大部分虚拟机都采用这种算法
    • 可以解决循环依赖的垃圾对象的回收
    • 什么可以作为GC Root呢?
      • 虚拟机栈中栈帧中的局部变量表存储的对象句柄
      • 方法区的类属性所引用的对象
      • 方法区中常量所引用的对象
      • 本地方法栈中引用的对象

 回收策略:

  • 标记-清除算法
    • 利用引用计数法或者可达性分析法判定出无用的对象之后,对无用的对象进行标记,然后清空
    • 缺点
      • 空间问题:堆内存会产生大量的内存碎片,一方面造成了空间的浪费;
      • 效率问题:二如果要分配一块大的内存,还需要第二次触发GC,进行两次回收,效率低下;
  • 复制算法
    • 将堆区划分为两个区域,先使用其中的一块进行创建对象,垃圾回收的时候,将其中有用的对象复制到另一块区域整理好,无用的对象不需要管,将第一块区域全部清空
    • 缺点
      • 不能充分的利用内存空间
  • 标记-整理算法
    • 主要针对不经常回收的区域,比如老年代
    • 两块内存区域A和B,将A中需要清楚的对象移动到B中,将B中有用的对象移动到A中,这样一来B中就全为垃圾对象,直接清空就可以了
  • 分代收集算法
    • 分代回收垃圾机制,是基于这样一个事实:不同的对象,有不同的生命周期,因此呢,不同的生命周期的对象采用不同的回收算法,可以提高回收效率;JVM把堆内存划分为以下四块:
      • Eden区(新生代):所有刚创建的对象都放到Eden区域中,Eden的目的就是清除掉那些生命周期短的对象,对应Minor GC,采用效率较高的复制算法;
      • Survivor1、Survivor2区(存活区):Eden区采用复制算法用到这两个区域进行复制以及清除;
      • Tenured Gen(老年代):当经历过15次(默认)垃圾回收以然还存活的对象,将其放入老年代,老年代中存放的都是一些生命周期较长的对象,对应Major GC/Full GC(全部区域),因为这一块区域垃圾回收的频率相对较低一点,因此采用标记-整理算法;
    •  

      JVM垃圾回收_第1张图片

       

    •  垃圾回收过程:

      •  

        1.新创建的对象都存储在Eden中;

        2.当Eden区存储达到一定比例之后,会触发Minor GC,将有用的对象复制到Survivor1中,清空Eden区;

        3.当Eden区再次满之后,将Eden和Survivor1中有用的对象复制到Survivor2中,同时清空Eden区和Survivor1区;

        4.当Survivor区中对象经历过15次(默认)垃圾回收,就将其复制到Tenured Gen/Old区域中;

        5.当Tenured Gen区满了,会触发一次Full GC,进行一次全面清理。

你可能感兴趣的:(JVM)