GC常用算法
一、首先什么是垃圾(garbage)?
没有引用指向的一个或多个对象叫做垃圾;
二、如何找到这些垃圾
一般有两种方法:
-
- 引用计数
- 根可达算法
1、第一种叫做引用计数法(reference count),有一个引用指向一个对象,计数就加1 ,直到这个数为0,就会被当作垃圾。
2、引用计数 不能解决一个问题(循环引用),如果根据引用计数法,这些都不是垃圾,可是没有其他引用指向这一团,那他们就是一团垃圾;那么根可达算法就能够解决,根可达算法的意思就是从根上开始搜索,
当一个程序启动之后马上需要的那些对象就叫做根对象,所谓的Root Searching是首先找到根对象,然后从根对象往下一直找,找到那些被引用的对象。
名词解释:
-
- 根可达算法:从根上对象开始搜索;
- 线程栈变量:一个main方法开始运行,main线程栈中的变量调用了其他方法,main栈中的方法访问到的对象叫根对象;
- 静态变量:T.class对静态变量初始化能够访问到的对象叫做根对象;
- 常量池:如果一个class能够用到其他class对象叫做根对象;
- JNI指针:如果调用了本地方法,本地的对象就叫做根对象;
- 根对象:一个程序启动马上用到的对象叫做根对象
三、GC Algorithms(常见的垃圾回收算法)
GC常用的算法有三个:
-
- Mark-Sweep(标记清除)
- Copying(拷贝)
- Mark-Compact(标记整理)
1、第一个是标记清除,就是把垃圾标记出来,然后把回收对象清理掉,就这么简单,首先找到那些有用的,没有用的标记出来然后清理掉。
标记清除算法有它自己的问题存在,我们从根找到了那些在用不可回收的,然后标记出可以回收的,清除之后就变成了空闲的,这种算法相对简单,在存活对象较多的时候效率比较高,这种算法需要扫描两遍,第一遍是找到那些有用的,第二遍是把那些没有用的找出来然后清理掉,执行效率偏低,容易产生碎片。
2、第二个是复制(Copying)算法,非常简单,就是把内容一分为二,把有用的拷贝到没用的一边,然后把剩下的全部清除,适用于存活对象较少的情况,只扫描一次,效率提高了很多而且没有碎片产生,但是浪费空间,移动复制对象要调整对象的引用。
3、第三个是标记整理(标记压缩)Mark-Compact 就是把所有对象整理的过程,清理的过程同时压缩,有用的全部往前走,剩下的大片空间就清理出来了,空间连续而且没有碎片。
标记整理算法依然有他的问题,在此过程中扫描两次而且还需要移动对象,第一次先找出有用的 第二遍才开始移动,移动过程中如果是多线程还需要进行同步,效率上肯定是降低很多,但是不会产生碎片,方便对象分配,不会产生内存减半。