JVM 垃圾回收算法

1.根搜索算法
    JVM使用根搜索算法判断一个对象是否可以回收,而不是使用所谓的“引用计数”算法。引用计数算法给每个对象添加一个引用计数器,每当有一个地方引用到该对象,则计数值加1;当引用失效时,计数值减1;任何时候只要对应计数值为0则表明对象不可能再被使用。但Java语言中没有选用该算法来管理内存,主要原因是它很难解决对象之间相互循环引用的问题。
    根搜索算法的基本思路是:通过一系列的名为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(用图论的话来说就是从GC Roots到这个对象不可达)时,则证明该对象是不可用的。所以它们将会被判定为可回收的对象。在Java语言中,可作为GC Roots的对象包括下面几种:
  • 虚拟机栈(栈帧中的本地变量表)中的引用的对象
  • 方法区中的类静态属性引用的对象
  • 方法区中的常量引用的对象
  • 本地方法栈中JNI(Native方法)的引用对象
    Java中对引用进行了扩充,将引用分为以下四种:
  • 强引用;类似“Object obj = new Object()”,在程序中普遍存在。只要强引用还存在,垃圾收集器永远不会回收该对象。
  • 软引用:通过该引用可以访问关联的对象,当JVM将要发生内存溢出异常之前,软引用所指向的对象被回收。JAVA中使用SoftReference来实现。
  • 弱引用:可以访问关联对象,无论当前内存是否足够,在垃圾回收时都会被回收。使用WeakReference实现弱引用。
  • 虚引用:不能访问关联的对象。与引用队列一起使用,在对象被回收之前该引用被添加到关联的引用队列中。使用PhantomReference实现虚引用。
    生存还是死亡:要真正宣告一个对象死亡,至少要经历两次标记的过程。如果对象在进行根搜索后发现不可达,那它将会被第一次标记并且进行一次筛选,筛选的条件是该对象是否有必要窒息感finalize方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过了【一个对象的finalize方法最多只会被系统自动调用一次】,虚拟机将这两种情况视为“没有必要执行”;如果有必要执行,则放到一个名为F-Queue的队列中,并在稍后由一条虚拟机自动建立的、低优先级的finalizer线程去执行。这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束。finalize方法时对象逃脱死亡命运的最后一次机会【只要重新与引用链上的任何一个对象建立关联即可】。若成功自救,则在第二次标记时,对象将被移出“即将回收“的集合。如果没有逃脱,则这个对象真的就离死不远了。
2.垃圾搜集算法
  • 标记--清除算法:首先进行标记出所有需要回收的对象,标记完成后统一回收掉所有被标记的对象。缺点:效率不高,会暂停用户线程;清除之后会产生大量不连续的内存碎片;
  • 复制算法:将可用内存分为大小相等的两块,每次只使用其中一块。当这一块的内存用完了,就将存活的对象复制到另一块上,然后把已使用过的内存空间一次清理掉。实现简单,运行高效,但代价是将内存缩小了一半。该算法被使用来回收新生代。研究表明,新生代中的对象绝大部分是朝生夕死的,所以不需要按1:1的比例来划分内存空间而是将内存划分为一块较大的Eden空间和两块较小的Survivor空间,每次只使用Eden和其中的一块Survivor。当回收时,将Eden和Survivor中还存活的对象一次性的拷贝到另外一块Survivor空间上,然后清理Eden和刚刚使用的Survivor空间。而当Survivor空间不够用时,需要依赖其他内存(老年代)进行分配担保。即当另外一个Survivor空间没有足够的空间存放上一次新生代收集下来的存活对象时,这些对象将直接通过分配担保机制进入老年代。
  • 标记--整理算法:老年代中的对象一般生存周期较长,所以使用该算法来回收。该算法的标记阶段与标记清除算法一致,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后清理掉边界以外的内存。可以避免标记清除算法产生的内存碎片。
  • 分带收集算法:根据对象的存活周期不同将内存划分为几块,一般划分为新生代和老年代,新生代中,每次垃圾收集时都发现有大批的对象死去,只有少量存活,选用复制算法收集;而老年代因为存活率高,没有额外的空间进行分配担保,就必须使用标记清理或者标记整理算法,一般采用后者。
3.CMS收集器
    是以获取最短停顿时间为目标的收集器。收集器的整个过程分为4个步骤,包括:
  • 初始标记:该阶段会短暂暂停用户线程,标记GC Roots能直接关联到的对象,速度很快;
  • 并发标记:进行GC Roots Tracing的过程,该阶段是与用户线程并发的;时间较长
  • 重新标记:修正并发标记期间,因用户线程继续运行而导致标记产生变动的那一部分对象的标记目录,会暂停用户线程,多个标记线程并发标记,较第一阶段时间长,但远比第二阶段短
  • 并发清除:与用户线程一同工作,清理可回收的对象
    缺点:无法处理浮动垃圾,这部分垃圾出现在标记过程之后,只能留待下一次GC时清理;因为是基于标记清除算法的,所以会产生内存碎片;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值