7. 垃圾回收(Garbage Collect)
7.1 如何确定一个对象是垃圾?
想要进行垃圾回收,要知道垃圾满足什么条件?
7.1.1 引用计数法
对于某个对象而言,只要程序中持有该对象的引用,就说明这个对象不是垃圾,如果该对象没有任何指针对其引用,那它就是垃圾。
弊端:如果AB互相持有引用,会导致永远不能被回收。
7.1.2 可达性分析
通过 GC Root 的对象,开始向下寻找,查看对象是否可达。
能作为GC Root: 类加载器、Thread、虚拟机栈中的本地变量、static成员、常量、本地方法栈的变量等。
7.2 垃圾收集算法
已经可以找到那些对象属于垃圾,那怎么进行回收?
下面是一些常用的垃圾回收算法。
7.2.1 标记-清除(Mark-Sweep)
标记: 找出内存中需要回收的对象,并进行标记。
此时堆中所有对象都会被扫描一遍,从而才能确定回收的对象,比较耗时
清除: 清除掉被标记需要回收的对象,释放出对应的内存空间
缺点
1)标记和清除两个过程都比较耗时,效率不高,遍历所有空间
2)会产生大量不连续的内存碎片会导致程序运行过程中分配大对象时,
无法找到足够的内存而不得不再次出发另一次垃圾回收。
7.2.2 复制(Coping)
将内存划分为两块相等的区域,每次只是用其中一块,如图所示
当其中一块内存使用完了,会将存活的对象复制到另一块空间,然后把已使用的空间清除。
缺点:空间利用率降低。
7.2.3 标记-整理(Mark-Compact)
标记过程与“标记-清除”算法一样,后续是将所有存活的对象都向一端进行移动,然后直接清理掉端边界以外的内存。
移动整理之后
7.3 分代-收集算法
上面介绍了3种垃圾收集算法,堆内存中使用的是哪个算法?
Young区 : 复制算法(对象在分配之后,生命周期较短,Young区复制效率高)
Old区:标记清除或标记整理。(Old区对象存活时间比较长)
When I let go of what I am , I become what I might be.
走出舒适圈,遇见更好的自己。