JVM之垃圾回收

JVM之垃圾回收

市面上有关JVM垃圾回收的文章不少,有些是针对垃圾收集器,有些是介绍垃圾回收算法,也有些各方面都有涉及。本文但愿能作一个比较全面的总结,最关键的是造成本身的语言,有本身的理解和沉淀。html

1、为何须要垃圾回收

你们都知道,java语言的内存是动态分配的,不像C++语言还须要开发者专门干预,在必定程度上能够提升开发效率。那么你们可能疑问:既然不须要咱们开发者关心,咱们为何还要讨论?做为一个程序语言的驾驭者,必然须要掌握该语言的方方面面,包括底层的原理和机制。
Java语言使用了内存动态分配和垃圾回收技术,掌握这些不只能够提升本身的逼格,并且为后续的JVM调优打下扎实的基础,让本身离架构师更近一步。java

2、哪些内存须要回收

JVM的内存结构包括五大区域:程序计数器、虚拟机栈、本地方法栈、堆区、方法区。其中程序计数器、虚拟机栈、本地方法栈3个区域随线程而生、随线程而灭,所以这几个区域的内存分配和回收都具有肯定性,就不须要过多考虑回收的问题,由于方法结束或者线程结束时,内存天然就跟随着回收了。而Java堆区和方法区则不同,这部份内存的分配和回收是动态的,正是垃圾收集器所需关注的部分。
垃圾收集器在对堆区和方法区进行回收前,首先要肯定这些区域的对象哪些能够被回收,哪些暂时还不能回收,这就要用到判断对象是否存活的算法。算法

一、引用计数法多线程

在这种方法中,堆中每一个对象实例都有一个引用计数。任何引用计数器为0的对象实例能够被看成垃圾收集。
引用计数是垃圾收集器中的早期策略。该方法看似很实用,可是解决不了循环引用的问题(好比循环链表)。架构

二、可达性分析算法并发

从一个节点GC ROOT开始,寻找对应的引用节点,而后寻该引用节点的引用节点,当全部的引用节点寻找完毕以后,剩余没有被引用的节点将会被断定为是可回收的对象。布局

三、引用分类spa

在Java语言中,将引用又分为强引用、软引用、弱引用、虚引用四种,这四种引用强度依次逐渐减弱。垃圾回收算法都是基于强引用而言的。.net

3、垃圾回收算法

一、标记-清除算法线程

标记-清除算法从根集合(GC Roots)开始扫描,对须要继续存活的对象进行标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收,以下图所示。

图片描述

标记-清除算法只需对不须要存活的对象进行处理,在存活对象比较多的状况下极为高效,可是会形成内存碎片。

二、复制算法

复制算法的提出就是为了解决内存碎片的问题,以下图所示。复制算法虽然解决了内存碎片的问题,可是浪费一半内存。另外在对象存活率很高的时候,复制成本会很是高。

图片描述

三、标记-整理算法

标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,所以成本更高,可是却解决了内存碎片的问题。具体流程见下图:

图片描述

四、分代收集算法

通常状况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特色是每次垃圾收集时只有少许对象须要被回收,而新生代的特色是每次垃圾回收时都有大量的对象须要被回收,那么就能够根据不一样代的特色采起最适合的收集算法。
新生代采用复制算法;老年代采用标记-整理算法。

其中年轻代内存分配过程以下:
1) 绝大多数刚建立的对象会被分配在Eden区,其中的大多数对象很快就会消亡;
2) 最初一次,当Eden区满的时候,执行Minor GC,将消亡的对象清理掉,并将剩余的对象复制到一个存活区Survivor0;
3) 下次Eden区满了,再执行一次Minor GC,将消亡的对象清理掉,将存活的对象复制到Survivor1中,而后清空Eden区;
4) 将Survivor0中消亡的对象清理掉,将其中能够晋级的对象晋级到Old区,将存活的对象也复制到Survivor1区,而后清空Survivor0区;
5) 而后跳到第三步,当两个存活区切换了几回(HotSpot虚拟机默认15次,用-XX:MaxTenuringThreshold控制)以后,仍然存活的对象,将被复制到老年代。

图片描述

4、垃圾收集器

图片描述

一、新生代收集器

1) Serial收集器
单线程收集器
2) ParaNew收集器
Serial收集器的多线程版,关注缩短垃圾收集时间。(使用-XX:+UseParNewGC开关来控制使用ParNew+Serial Old收集器组合收集内存;使用-XX:ParallelGCThreads来设置执行内存回收的线程数。)
3) Parallel Scavenge收集器
关注CPU吞吐量,即运行用户代码的时间/总时间。(使用-XX:+UseParallelGC开关控制使用Parallel Scavenge+Serial Old收集器组合回收垃圾(这也是在Server模式下的默认值);使用-XX:GCTimeRatio来设置用户执行时间占总时间的比例,默认99,即1%的时间用来进行垃圾回收;使用-XX:MaxGCPauseMillis设置GC的最大停顿时间;使用-XX:+UseAdaptiveSizePolicy能够进行动态控制Eden/Survivor比例,老年代对象年龄,新生代大小等。)

二、老年代收集器

1) Serial Old收集器
单线程收集器
2) Parallel Old收集器
Parallel Scavenge收集器的老年代版本(使用-XX:+UseParallelOldGC开关控制使用Parallel Scavenge +Parallel Old组合收集器进行收集。)
3) CMS收集器
多线程,优势是并发收集(用户线程能够和GC线程同时工做)

三、G1收集器

特性:
1) 首先收集尽量多的垃圾(Garbage First)
内部采用了启发式算法,找出具备高收集收益的分区进行收集。
2) 并行和并发
和CMS类似,能够作到用户线程和GC线程同时工做。
3) 内存布局调整
将整个堆划分为多个大小相等的独立区域(Region),新生代和老年代再也不是物理隔离,它们都是一部分Region(不须要连续)的集合。每一个分区均可能随G1的运行在不一样代之间先后切换。
G1划分了一个Humongous区,它用来专门存放巨型对象。
4) GC模式
G1提供了两种GC模式,Young GC和Mixed GC,两种都是Stop The World(STW)的。

图片描述

5、引用文献

[1] https://blog.csdn.net/ft30597...
[2] https://www.cnblogs.com/1024C...
[3] https://blog.csdn.net/x_i_y_u...
[4] https://www.jianshu.com/p/e99...
[5] https://blog.csdn.net/foolish...
[6] https://blog.csdn.net/coderli...
[7] https://www.cnblogs.com/ASPNE...

相关文章
相关标签/搜索