UML软件工程组织

解析Java对象引用与JVM自动内存管理(1)
作者:杨扬 本文选自:赛迪网 2002年11月22日

对象引用应用程序设计接口是JDKTM1.2中新定义的。该应用程序设计接口允许应用程序以对象引用的方式与JVM的内存管理器进行交互。当应用程序需管理大量内存对象或者在新的Java对象创建之前需删除原有对象时,Java对象引用应用程序设计接口具有相当大的用途,例如:

  • 基于Web的应用程序常常要求显示大量图片,当用户离开某一Web页时,往往不能确定是否能够顺利的返回。在这种程序中,应用Java对象引用API可以创建这样一个环境,即当堆内存以最小程度运行时,内存管理器创建对象。当用户返回时,应用程序就会重新载入已经创建的图片。
  • 应用对象引用队列可以创建这样一个环境,当通过对象引用获得某一对象时,应用程序得到通知。然后,应用程序就可以对相关对象进行清除操作,同时使这些对象在内存管理器中合法化。

内存管理器的工作机制

下面将首先介绍未嵌入引用对象时内存管理器的工作机制,然后讨论引用对象加入之后Java堆发生的变化。

内存管理器的作用就是识别程序中不再使用的对象,并且回收其内存。

一个Java应用程序由一系列线程组成,每个线程执行一系列方法,而每个方法通过参数或局部变量来引用对象。这些引用属于引用集合中的一部分,直接进入应用程序。另外,引用集合中还包括类库中定义的静态引用变量,以及通过Java本地接口(JNI)API获得的引用。引用集合中的所有引用对象都可以被当前应用程序获取,而不必被回收。同样地,这些对象可能包含对其它对象的引用,也可以被应用程序获取,依此类推。Java堆中的其它对象视为不可获取的,而所有这些不可获取的对象在内存管理中也是合法的。如果一个不可获取的对象使用finalize()方法,任务就交给了对象所调用的收尾器(finalizer)。在内存回收期间,不具有收尾器的不可获取对象和已经调用收尾器的对象被简单回收。

内存回收的算法是不断变化的,共性的方面是从引用集合中识别可获取的对象以及回收被其它对象占据的内存空间。

加入引用对象之后的引用与常规引用的区别在于,引用对象中的引用专门由内存管理器来处理。引用对象封装了其它一些对象的引用,我们称之为指示对象。在引用对象创建的同时,也就定义了该引用对象的指示对象。

Java对象引用

图1所示为对象引用应用程序设计接口中定义的类层次。其中SoftReference类、WeakReference类和PhantomReference类中分别定义了三种引用对象以及相应的三种获取对象的能力。因此按照由强到弱,对象可获取程度可划分为如下五种类型:强获取(strongly reachable)、次获取(softly reachable)、弱获取(weakly reachable)、虚获取(phantomly reachable)和不可获取(unreachable)。

图1 对象应用类层次

根据应用程序要求,对象可以是强引用(strong references)、次引用(soft references)、弱引用(weak references)、虚引用(phantom references)的任意组合。为了确定对象的可获取程度,JVM内存管理器从引用集合出发遍寻堆中所有到对象的路径。当到达某对象的任意路径都不含有引用对象时,则称该对象具有强获取能力;当路径中含有一个或几个引用对象时,根据内存管理器所查询的引用对象的类型分别归为次获取、弱获取、虚获取。

另外,对象引用API中还定义了引用对象队列(java.lang.ref.ReferenceQueue),这是内存管理器对引用对象进行管理的一种简单数据结构。值得注意的是,在进行引用对象定义时,要求phantom reference对象必须产生于一个引用对象队列,而soft reference和weak reference对象则无此限制,如:

ReferenceQueue queue = new ReferenceQueue();
PhantomReference pr = new PhantomReference(object, queue);



版权所有:UML软件工程组织