jvm的垃圾回收主要是针对java堆这块内存空间,因为java的虚拟栈是随着线程的销毁而自动回收的,而方法区的垃圾回收条件极其苛刻。
java堆中存放着运行期间的对象实例,随着程序的运行实例越来越多,不回收垃圾就会产生OOM异常,而怎么判断一个对象是否是垃圾呢,下面是几种常用的垃圾判别法。
1引用计数法
基本想法就是 一个对象,如果有地方在引用它,那么它就不是垃圾,因此呢,我给这个对象创建一个引用计数器,对象 被引用一次,计数器就+1,引用失效,计数器-1,垃圾回收的时候一看这个对象计数器值为0,说明这个对象没被引用了,就被当作垃圾回收了。这个算法非常高效,但是存在的问题就是两个对象互相引用,这样这两个对象就永远无法被回收。
2根搜索法
这个方法的基本思路是,从一些根节点,称为“GC Roots”,为起始点往下搜索,形成一条引用链,在引用链之外的对象被视作垃圾。java语言中的“GC Roots”有如下几种:帧栈中本地变量表中引用的对象、方法区中类静态属性引用的对象、方法区中常量引用的对象、本地方法栈中JNI引用的对象。
在jvm的垃圾回收实现中经常会使用如下的算法
1 标记清除算法
在这种回收机制中,分为两个过程,一是标记,再就是清除,标记阶段就是用根搜索法来判断对象是否需要回收,清除就是回收内存空间。这个算法是垃圾回收中最基本的算法,许多高级的垃圾回收算法都是根据它为基础。这个算法的缺点是效率低,回收后的内存空间过于碎片化。
2 复制算法
针对标记清除算法的效率问题,复制算法给出的解决方法是,将内存空间一分为二,每次只用其中一块空间,当进行垃圾回收时,把活着的对象复制到另一块空间中,清除时将原空间全部清除,这样效率既高也解决了内存碎片,缺点就是太废内存了。
3 标记整理算法
过程和标记清除算法类似,区别就是它不直接把垃圾空间清除掉,而是将活着的对象都移动到一起,剩下的空间就是垃圾空间了,这时候直接清除掉就行。
4 分代回收算法
分代回收法就是根据对象的生存周期,分为老年代和新生代两个内存空间,对于新生代这种对象生成和死亡都比较快的区域使用复制算法进行回收,对于老年代则使用标记清除或标记整理算法。
jvm的几种垃圾回收策略