GC

1.什么是垃圾回收

在程序中会产生各种各样的问题,这些数据可能是没有但是一直存在的,就需要把这些无效的资源进行垃圾回收,释放资源

1.1C/C++语言的垃圾回收

1.1.1 在c/c++语言中,没有垃圾回收机制,是通过new关键字申请内存资源,通过delete关键字释放资源

1.1.2 如果程序员在程序中没有鞋delete关键字,那么资源就会一直存在程序中,最终会导致内存溢出

1.2 java语言垃圾回收
为了让程序员更加专注在代码实现上,不用过多的考虑在代码释放上,java语言中有自动垃圾回收机制,也接收CG

2.垃圾回收的常见算法

自动化管理内存,垃圾回收需要一套算法进行计算,哪些是有效对象,哪些是无效对象,把无效对象进行回收

2.1 引用计数法
引用计数是历史悠久的一种算法,早George E. Collins在1960的时候首次提出,50 年后的今天,该算法依然被很多编程语言使用

2.2 原理
假设有一个A对象,任何一个对象对A的引用计算机+1(一直有对象引用A对象成功,会一直+1),如果引用失败计算机-1,如果A对象计算机为0时,说明A对象没有引用

2.3 优缺点
优点:
实时性较高,无需等到内存不够的时候,才开始回收,运行时根据对象的计数器是否 为0,就可以直接回收。

在垃圾回收过程中,应用无需挂起。如果申请内存时,内存不足,则立刻报 outofmember 错误。
区域性,更新对象的计数器时,只是影响到该对象,不会扫描全部对象。

缺点:
每次对象被引用时,都需要去更新计数器,有一点时间开销。

浪费CPU资源,即使内存够用,仍然在运行时进行计数器的统计。

无法解决循环引用问题。(大的缺点)

2.2 标记清楚法
标记:从根节点开始标记引用对象
清除:未被标记的对象就是垃圾对象,可以清除

2.3 原理
GC
上图,是程序运行期间所有的对象状态,他们的表示是0(默认0表示未表示,1表示标识),假设程序内存耗尽,JVM将会停止应用程序运行开启GC,开始标识工作,标识后如下图
GC
此 时已经完成了第一阶段标记。接下来,就要执行第二阶段清除了,那么清除完以后,剩 下的对象以及对象的状态如下图所示。
GC
可以看到,没有被标记的对象将会回收清除掉,而被标记的对象将会留下,并且会将标 记位重新归0

2.3 优缺点
优点
标记清除算法解决了引用计数算法中的循环引用的问题,没有从root节点引 用的对象都会被回收。
缺点
效率较低:标记和清除两个动作都需要遍历所有的对象,并且在GC时,需要停止应 用程序,对于交互性要求比较高的应用而言这个体验是非常差的。 通过标记清除算法清理出来的内存,碎片化较为严重,因为被回收的对象可能存在于 内存的各个角落,所以清理出来的内存是不连贯的。

3.1 标记压缩算法
标记压缩算法是在标记清除算法的基础之上,做了优化改进的算法。和标记清除算法一 样,也是从根节点开始,对对象的引用进行标记,在清理阶段,并不是简单的清理未标 记的对象,而是将存活的对象压缩到内存的一端,然后清理边界以外的垃圾,从而解决 了碎片化的问题。
白色空的,灰色有数据,黑色标识,和数组机制一样把标识的往前移
GC
3.1.1 优缺点
优缺点同标记清除算法,解决了标记清除算法的碎片化的问题,同时,标记压缩算法多 了一步,对象移动内存位置的步骤,其效率也有有一定的影响。
2.4 复制算法
内存被分为大小相同两块区域,一块为From,一块为To,程序向From区域存放数据,当from数据即将满了的情况下,进行垃圾回收:首先标记垃圾对象,然后将没有标记的对象复制到To当中
GC
然后回头将From所有区域清空,然后角色交换,From和To交换,保证To永远为空
GC
2.5 JVM中年轻代内存空
2.5.1 年轻代当中分为Eden去和From和To区,其中From和To区的大小时相同的,程序向Eden去和From区存放数据,当数据即将满了的情况下
GC
2.5.2Eden区会将活跃对象存放到To区,From区会将年龄小的对象存放到To区,那么年龄大的存放到Old年老代区域当中
GC
2.5.3清空Eden去和Old区的所有数据,然后将From区角色和To区角色互换,这样保证To区为空
GC
2.5.4当垃圾回收机制反复运行时,那么To区可能数据饱和,如果数据饱和则将所有对象转移到Old年老区

2.6 分代算法
分代算法其实就是这样的,根据回收对象的特点进行选择,在jvm中,年轻代适合使用复制算法,老年代适合使用标记清除或标记压缩算法。