## **什么是垃圾回收机制**
垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,编程人员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理。可通过调用`System.gc`方法来"建议"执行垃圾收集器,但其是否可以执行,什么时候执行却都是不可知的。
## **垃圾回收主要回收哪块内存区域**
Java内存运行时内存结构中**程序计数器**、**虚拟机栈**、**本地方法栈**3个区域随着线程的生存而生存的。内存分配和回收都是确定的。随着线程的结束内存自然就被回收了,因此不需要考虑垃圾回收的问题。而Java**堆**则是由各线程共享,内存的分配和回收都是动态的。因此垃圾收集器所关注的都是这部分内存。
## **垃圾回收的对象**
如果这个对象没有被其他对象所引用那么该对象就是无用的或者说不可达的,就会被回收。
## **如何判断对象是否被引用**
采用**根搜索算法**的基本思路就是通过一系列名为”GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
GCRoots的对象包括下面几种:
* 虚拟机栈(栈帧中的局部变量表)中引用的对象
* 堆(JDK8)/方法区(JDK6)中的类静态属性引用的对象。
* 常量池中常量引用的对象
* 本地方法栈中JNI(Native方法)引用的对象
![](https://img.kancloud.cn/8f/68/8f681c073f200a7889a02f75b28f500c_755x409.jpg)
## **垃圾回收机制策略**
GC在识别到可回收资源后会根据不同的算法进行回收,主要使用以下四个算法。
* 标记清除算法
* 复制算法
* 标记压缩算法
* 分代算法
#### **标记清除算法**
该算法有2个阶段
1. 标记:找到所有可访问的对象,做个标记
2. 清除:遍历堆,把未标识的对象回收
缺点:
1. 回收时,应用需要挂起
2. 标记和清除都需要遍历堆,效率低
3. 定点清除会形成很多不连续的内存空间,造成内存碎片化。
#### **标记压缩算法**
标记压缩算法和标记清除算法很像,但是他提供了解决内存碎片化的方案。
* 任意顺序 : 即不考虑原先对象的排列顺序,也不考虑对象之间的引用关系,随意移动对象
* 线性顺序 : 考虑对象的引用关系,例如a对象引用了b对象,则尽可能将a和b移动到一块
* 滑动顺序 : 按照对象原来在堆中的顺序滑动到堆的一端
缺点:缺点压缩阶段,由于移动了可用对象,需要去更新引用
#### **复制算法**
堆中内存模型主要包含:Eden、From、To、老年代。对象在堆中的存储流
1. 新创建的对象存入Eden、当Eden满时会触发一次young gc,把还活着的对象copy到From区,然后清空Eden区域。
2. Eden再次触发young gc时,会扫描Eden区和From区,把活着的对象copy到To区,然后清空Eden和From区域。
3. Eden再次触发young gc时,会扫描Eden区和To区,把活着的对象copy到From区,然后清空Eden和To区域。
4. 部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认是15),最终如果还是存活,就存入到老年代。
优点:对真块区域进行清除、性能高,同时可以解决内存碎片化问题。
缺点:From和To区实际是2块一样的内存空间,会造成一定的内存浪费。
#### **分代算法**
JVM根据新生代和老年代的特点采用不同的收集算法
1. 新生代中,每次进行垃圾回收都会发现大量对象死去,只有少量存活,因此比较适合复制算法。只需要付出少量存活对象的复制成本就可以完成收集。
2. 老年代中,因为对象存活率较高,没有额外的空间进行分配担保,所以适合标记-清理、标记-整理算法来进行回收。
## **Minor GC和Full GC**
**Minor GC**
概念:新生代的垃圾回收、比较频繁、回收速度快。
触发机制:Eden区满时会触发Minor GC.
**Full GC**
概念:老年代的垃圾回收、速度比Minor GC 慢很多。
触发机制:当年老代满时会引发FullGC,FullGC将会同时回收年轻代、年老代。通常一次FUll GC会伴随至少一次的MinorGC。