原理是此对象有一个引用就增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只回收计数为0的对象。
缺点:无法处理循环引用的问题
此算法执行分两阶段:
1. 从引用根节点开始标记所有被引用的对象
2. 遍历整个堆,把未标记的对象清除。
缺点:此算法需要暂停整个应用,会产生内存碎片
此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。
垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域,之后进行相应的内存整理,不会出现碎片问题。
缺点:需要两倍内存空间
在标记-清除之后重新整理内存,避免了内存碎片问题和复制算法的空间问题
内存碎片会导致无法分配大块的内存空间以及程序运行效率降低
垃圾回收的起点是一些根对象:
1.没有被任何外部对象引用的栈中的对象,即系统内运行的所有线程分配在栈中的变量,该对象就是“根”
一旦线程跑到某一个变量所在的作用域之外,那么该变量就变成了垃圾
2.静态变量在任何时候都是“根”对象
3.寄存器
根据这些根集对象检测所有对象的可达性即可判断对象是否可以回收
可达性:某个对象的内存地址是否有被引用
把一个对象置为NULL并不能保证该对象会被回收
测试类:
public class TestNull {
public static void main(String[] args) {
Map map = new HashMap<>();
Object obj = new Object();
map.put("obj", obj);
obj = null;
System.out.println(map.get("obj"));
}
}
运行可以看到map仍然可以引用到obj,分析如图:
因为HashMap仍然引用了new Object()对象,所以其并不会被JVM回收
tips:
1.如果希望集合中的对象被回收,调用其相应的remove()方法从集合中删掉即可
2.obj = null;语义是把让变量obj不再指向任何物理内存
而不是把obj所指向的对象的物理内存置为null