内存分配与回收策略
判断对象已死的算法
-
引用计数器法可以简单的概括为:给对象添加一个引用计数器,每当有一个地方引用该对象时,计数器+1,当引用失效时,计数器-1,任何时刻,当计数器为0的时候,该对象不在被引用。客观的说,引用计数器的实现简单,判断效率也高,大部分场景下是一个不错的选择。但是当前主流的JVM均没有采用标记清除算法,原因在于,它很难解决对象之前互相循环调用的情况。
-
可达性分析算法
在主流的商用程序语言(c、c++、c#、java)的主流实现中,都是通过可行性分析判断对象是否存活,这个算法的思想就是通过一系列的成为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径成为引用链,当一个对象到“GC Roots”没有任何引用链相连,则证明此对象是不可用的
-
在java中,可以作为GC Roots的对象包括以下几种:
-
虚拟机栈中引用的对象
-
方法区中类静态属性引用的对象
-
方法区中的常量引用的对象
-
本地方法栈中JNI(即一般说的Native方法)的引用的对象
-
-
什么是引用?
在JDK1.2之前,引用被定义为当一个reference类型的数据代表的是另外一块内存的起始地址,该类型的数据被称为引用。在JDK1.2之后对引用进行重新的扩充,分为强引用、软引用、弱引用、虚引用4种,这四种引用的强度依次递减
-
强引用
强引用是在代码中普遍存在的,类似于Object o=new Object(),只要强引用一直存在,垃圾回收器就永远不会回收被引用的对象
-
软引用
软引用用来描述一些还有用但非必须的对象,对于软引用关联着的对象,当内存溢出异常发生之前,通过垃圾回收进行二次回收。如果二次回收完成之后,系统内存任然不够,才会抛出内存溢出异常,在JDK1.2以后用SoftReference类来实现软引用
-
弱引用
弱引用也是用来描述非必须对象的,但是强度比软引用更弱一些,它仅仅能生存到下一次垃圾回收之前。当垃圾收集时,无论内存是否足够,弱引用的对象都要被回收,在JDK1.2以后采用WeakReference类来实现弱引用
-
虚引用
虚引用是一种最弱的引用关系,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过一个虚引用来获取一个实例对象。为一个对象设置虚引用的唯一目的就是 该对象在垃圾回收是收到一个系统通知,JDK1.2以后用PhantomReference实现虚引用
垃圾回收算法
-
标记清除算法,如下图所示:这种算法有一个非常大的缺点就是会将内存碎片化,当需要在此空间中申请一个比较大的空间是会出现内存溢出现象
-
标记整理算法,如图所示这种算法相对于标记清除算法优点在于对对象所占用的内存进行整理可以腾出一块地址相连接的内存,只要申请的内存没有超过内存大小,就不会发生内存溢出异常,但是在现在的商业实现中并不会单一使用此算法