1 为什么不用引用计数
因为引用计数对循环依赖没有办法,比如
A a = new A();
B b = new B();
a.b = b;
b.a = a;
a = null;
b = null;
然后a、b就永远也回收不了了。
2 gc root
gc root就是gc可以明确的当前不能被回收的对象,有以下类型:
正在跑的线程对象;
线程栈中的局部变量;
正在使用的object monitor,比如某个对象调用了wait()函数;
等等。
注意,单例模式的对象也是可以被gc回收的。不用的类的对象也是会被gc卸载的。
http://help.eclipse.org/kepler/index.jsp?topic=%2Forg.eclipse.mat.ui.help%2Fconcepts%2Fgcroots.html
3 判断一个对象是否可以被回收
如果gc root对象到该对象是不可达的,那么就是可以被gc回收的。
4 回收算法
4.1 标记回收
两趟,第一趟标记所有可以被回收的对象,第二趟回收。问题就是会造成很多的内存空洞。
4.2 复制回收
将内存分成两个区域,先标记,然后把活对象复制到另外一个区域,再将原区域的全部回收。
4.3 标记整理
先标记,然后把活的对象向前移动成连续的空间,剩余的空间就也是连续的了。
5 分代收集算法
先将堆区划分成新生代和老年代,老年代区域因为每次回收的对象少,所以就使用标记整理算法,新生代区域每次回收的对象多就使用复制回收算法。
将新生代再分成三个区域,一个eden、两个survivor,每次将eden和survivor A中的活的拷贝到survivor B区域中,然后回收掉eden和survivor A中的对象。
6 垃圾回收触发的时机
创建了一个新的对象并且放入eden区,发现放不下,就试图放入survivor区,还是放不下,就触发了对新生代的minor gc。
新生代到了一定的年纪,会移入老年代,如果空间不足,会触发full gc。