我们知道程序计数器、虚拟机栈、本地方法栈三个区域都是线程私有的,它们的生命周期都是随着线程而生,随着线程而亡,因此是不需要过多考虑回收的问题,而Java Heap(堆)与Method Area(方法区)不一样,必须考虑内存回收问题。
我们只有当程序运行的时候才会知道会创建哪些类,而这些类占用内存也是不同的,不会固定,都是动态的,即这部分的内存的分配与回收都是动态的,垃圾收集器关注的就是这部分内存。
VM判断对象是否死亡主要有两种方式,一种是通过计数器的方式,另外一种是通过引用链(根搜索算法):
1、计数器方式
这是很多教科书是提及到的方法,可以算是经典的一种方式。
(1)原理:通过引用一个计数器,每次对象被引用就会加1,当引用失败后,自然减1...如此下去,直到计数器为0(其实任何时刻都可能为0),那么可以认为此对象不可能再被引用了,也就是达到GC的条件。
(2)优点:简单容易实现,判断效率也高,计数器的操作并不占用过多资源。
(3)缺点:那很明显就是无法解决对象之间的循环引用问题,至于什么是对象之间的循环引用,可以通过下面的代码理解:
private Object instance = null; GCObject ojbA = new Object(); GCObject ojbB = new Object(); //对象之间的循环引用 objA.instance = objB; objB.instance = objA; //两个对象已经不能被引用 objA = null; objB = null; //这里开始GC system.gc();