垃圾对象判断与回收

了解GC如何进行垃圾回收,也就是垃圾回收器如何工做,咱们首先要了解这几个前置知识.如何判断一个对象是不是垃圾对象,方法区中加载的类元信息如何判断是无用类,垃圾回收算法,对象的最终标记.java

如何判断一个对象是不是垃圾对象

引用记数法

顾名思义,这个方法其实就是判断对象的引用数量来判断这个对象是不是垃圾对象.给对象添加引用计数器,每多一个引用则引用数量+1,每少一个引用则引用数量-1.当此对象引用数量为零,则对象为垃圾对象.这种方式实现简单且高效,可是这种方式存在着一种问题,也就是对象的循环依赖.假设如今有两个对象,他们互相引用值为null,且不存在其余对象对其引用也不存在这两个对象的使用,那么这时这两个对象应该就是垃圾对象,可是因为他们互相引用,因此没法被回收.算法

可达性分析算法

咱们仍是根据名字推测他的意思,可达性即这个对象能够到达,对可达性进行分析来判断对象是否存在引用,若是对象可达则不能回收,若是不可达则将对象标记为垃圾对象等待回收,这也是主流虚拟机采用的方式,那么这个可达性是什么呢,要了解这个概念,咱们首先须要了解GC Roots根节点.3d

GC Roots根

咱们都知道java是单根结构,能够根据一个Object根发展出一颗依赖树来.那么这个GC Roots根节点其实也有着殊途同归之妙.他一样的能够以GC Root做为根节点向下发展,发展出一颗依赖树,经过这个GC Root向下探寻,能够探寻到的对象咱们就称其为可达的.值得注意的一点是GC Root能够有多个.cdn

GC Roots根是什么

GC Roots有不少种类型,常见的好比说栈帧里的本地变量(指向堆内存的对象),静态变量等等对象

无用类

无用类(并不是学名)须要符合如下几个条件blog

  • 这个类的全部引用已经消失(被回收)
  • 这个类的class信息被回收(不能经过反射建立此对象的实例)
  • 这个类的类加载器被回收

垃圾对象标记

垃圾对象的标记实际上是分为两个阶段的,主要是看这个对象是否重写了Object类的finalize()方法.内存

经过可达性分析咱们能够对垃圾对象进行标记.可是对象实际上是有一个二次标记的过程的,重写finalize()方法能够进行第二次标记,若是对象没有重写这个方法则直接视为垃圾对象.这一些执行第二次标记的对象,会执行这个方法内的代码,若是在这个方法中把原本应该是垃圾对象的对象从新引用,好比设置一个成员变量并将这个实例赋给这个变量.那么这个对象就不会被视为垃圾对象,若是没有对其进行从新引用则此对象视为垃圾对象.虚拟机

垃圾回收算法

垃圾回收算法主要分为四种it

标记-清除算法

这个算法分为两个部分,"标记","清除".io

标记即上述内容,经过可达性分析算法,不可达对象标记,二次标记中没有自救的对象.

清除就是进行消除工做

这个算法具备两个问题,效率问题与空间问题.

  • 效率问题:因为垃圾对象存在不连续又没有引用,因此标记的过程很耗时
  • 空间问题:这种清除算法会形成一些微小的内存碎片,从而形成内存的损失.

内存碎片就是占用空间小无法放下其余对象的的小内存空间.

标记-复制算法

这个算法将一块内存区域分为彻底相等的两块,这两块只能使用一块,另外一块作什么用呢,用于垃圾清除后的空间整理.进行垃圾清除时,他会把当前这一半的全部存活对象依次移入到另外一半内存中去,移入完成后在对这一块内存进行总体回收.因为每次清理对象实际都存在一个整理的过程,因此这种算法不会产生垃圾碎片问题,又由于他是保留有用的对象,直接所有回收一块内存空间,速度天然也比标记-清除算法快不少.

标记-整理算法

标记过程都相同,整理首先是将存活对象向前移动,将全部存活对象移到前面去,那么此时会产生一个内存分界点,分界点一端所有都是有用对象,另外一端所有都是垃圾对象,这时候只须要对分界点的一端进行总体清理就能够了.这个算法一样不会产生垃圾碎片,效率也不低.

分代收集算法

分代收集算法并非像前三种算法那样作一个清除的步骤,他只不过是将堆内存分为了年轻代老年代,这样咱们就能够经过不一样的策略针对不一样的区采起不一样的垃圾收集算法.

相关文章
相关标签/搜索