第2章介绍了Java内存运行时区域的各个部分,其中程序计数器、虚拟机栈、本地方法栈三个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。每个栈帧中分配多少内存基本上在类结构确定下来时就已知的(尽管在运行期会由JIT编译器进行一些优化,),因此这几个区域的内存分配和回收都具有确定性,不需过多考虑回收的问题,因为方法结束或线程结束时,内存自然就跟着回收了。
垃圾收集器对堆进行回收前如何确定哪些对象“活着”,哪些对象已经“死去”(即不可能再被任何途径使用的对象)。
1 引用计数法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器都为0的对象就是不可能再被使用的。
该算法实现简单,判定效率高,在微软的COM(Component Object Model)技术、使用ActionScript3的FlashPlayer、Python语言以及在游戏脚本领域中被广泛应用的Squirrel中都使用了引用计数算法进行内存管理。
Java中没有选用引用计数算法来管理内存,其主要原因是因为它很难解决对象之间相互循环引用的问题。
2 根搜索算法
通过一系列的名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
在java语言里,可作为GC Roots的对象包括下面几种:
>虚拟机栈(栈帧中的本地变量表)中的引用的对象;
>方法区中类静态属性引用的对象;
>方法区中常量引用的对象;
>本地方法栈中JNI(一般说的Native方法)的引用的对象。