对java虚拟机垃圾回收的学习的总结

java垃圾回收机制是对无用信息对象进行检索,并且回收它们所占用的内存空间,使该部分空间可被再次使用。垃圾回收是不定时的发生。

判断对象是否为垃圾的算法

垃圾回收算法包含引用计数算法(Reference Counting Collector)、根搜索算法(Tracing Collector)

引用计数算法

堆中每个对象都对应一个引用计数器。

  • 当该对象被创建后首次赋值时,该引用值设置为1。
  • 一个新的地方要引用该对象时,引用值加1。
  • 当该对象的一个引用值被置为null或者超过了其生命周期或者引用别的对象时,引用值减1。
  • 当一个对象对应的引用值为0时,它将被等待回收。当它被回收后,它所引用的对象的引用计数器值都减1。

它的优缺点如下:

  1. 优点是速度快,可以在不打断程序运行的情况下交至运行,判断效率高;
  2. 缺点是难以检测出循环引用的对象。引用计数器增加程序运行的开销。

根搜索算法

从一系列GC Root出发,来对引用节点进行遍历,凡是不可到达的对象(它和GC Root没有任何引用链)都是无用信息对象,标记它们使之等待回收。

GC根对象包含如下:

  • 虚拟机栈中的引用对象(栈帧中的引用变量表)
  • 方法区的类的静态属性引用的对象
  • 方法区的常量引用的对象(这个还不没搞清楚,后续继续分析..)
  • 本地方法栈中引用的对象(这个还不没搞清楚,后续继续分析..)
  • 活跃线程

该算法是从离散数学的图论引入的。

标记回收对象的关键点分析

当判断是否为回收对象的算法开始运行时,如果此时采用的是根搜索算法,java程序将会被暂停(Stop the world, STW),这个情况被称为安全点(Safe Point)。在把查找到的无用信息对象进行回收之前,如果检测到部分对象重写了finalize方法并且还没有被执行过,则把这部分对象保存到一个F-Queue中。然后在一低优先级的线程中对该队列中的对象进行遍历来执行它们的finalize。此时若出现这种情况,一个对象的finalize方法被执行时,把该对象重新和引用链上某一对象建立关联,那么这个对象将通过这种自救的方式避免被回收。不然的话,它将被回收掉。

垃圾回收算法

Tracing算法(Tracing Collector) 或 标记—清除算法

对象被标记后将被回收,回收后会留下来内存碎片。未被标记的活动对象将不受影响。但是要额外维护一个空闲列表来记录空闲区域和大小,而且产生的内存碎片会妨碍后续的内存分配。

Compacting算法(Compacting Collector) 或 标记—整理算法

对象被标记后不是被清除掉,而是把所有未标记的活动对象向内存中的一端进行移动,端边界以外的内存将被清理掉,避免内存碎片。但是移动对象和更新引用地址将会导致GC增加执行时间。

Copying算法(Copying Collector)

建立两个面(对象面、空闲面),当对象面内存用完时,就把活动对象都copy到空闲面上,然后清理原来对象面的内存,把它变成新的空闲面,然后原来的空闲面变为新的对象面。

它有很多优点,比如标记阶段和copy阶段可以同时进行,只移动栈顶指针的位置即可,每次只copy一次内存所以高效,避免内存碎片。但是需要额外的一份相同大小的内存,所以整体上一次性分配的内存缩小了一半。

Adaptive算法(Adaptive Collector)

根据当前堆的使用情况来分析要采用哪种垃圾收集器算法

java堆

java堆基于Generation算法(Generational Collector)划分为新生代、年老代,持久代。这个划分主要基于一个事实:不同的对象具有不同的生命周期。不同的代存储不同生命周期的对象,采用的垃圾回收算法也不同。

新生代(Young Generation)

新创建的对象都将放到新生代内存中,新生代内存包含eden区和survivor区,survivor区又将包含survivor0和survivor1两个区。新创建的对象都将放入到eden区,若eden区满了之后,则把对象copy到survivor0区,若survivor0区也满了,就把对象copy到survivor1区,此时survivor1区变为新的survivor0,原来的survivor0变为新的survivor1。若对象在survivor区存活时间比较久,则该对象讲移入到年老代内存中。

年老代(Old Generation)

年老代的堆主要存储生命期长的对象和一些占用大内存的对象。当在新生代中的survivor的对象躲过一次GC,其年龄加1岁,若年龄增加到15岁,则该对象从新生代转移到年老代。

持久代(Permanent Generation)

持久代的堆主要存储静态文件(类和方法)和常量。在java8中采用了元空间(MetaSpace)取代了持久代。

android垃圾回收所采用的算法

待续

进阶

  • 虚引用为一个对象设置虚引用关联的唯一目的是希望能在这个对象被收集器回收时收到一个系统通知。那么这是如何做到的呢?
  • 离散数学的图论
  • 指针碰撞(Pointer Bumping)是什么
  • java回收中提到的句柄是什么
  • 新生代内存为什么是按照8:1:1,具体机制是什么