posts - 32, comments - 153, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

[转]解析Java对象引用与JVM自动内存管理

Posted on 2006-11-29 14:08 Zou Ang 阅读(431) 评论(0)  编辑  收藏 所属分类:

Java基础知识,打好基础才能更好地学习!
原帖地址:http://www.linuxmine.com/44702.html
对象引用应用程序设计接口是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);

  Soft References 应用实例
  
  下面以在基于web的应用程序中使用soft references为例,来说明Java对象引用与JVM的内存管理器进行交互的原理。
  
  当用户打开某一web页时,applet代码获得图片并且得到显示。如果在代码中同时创建了该图片对象的soft references,那么当用户离开该web页时,内存管理器对图片所分配的内存是否回收做出选择。当用户返回该web页时,在applet代码中使用SoftReference.get方法就会得到图片才内存中是否仍存在的消息。如果在内存管理器中未创建该图片,在web页上会很快得到显示;否则,applet代码就会重新获取。
  
  下面是Example.java的完整源代码。
  
  

import  java.awt.Graphics;
  
import  java.awt.Image;
  
import  java.applet.Applet;
  
import  java.lang.ref.SoftReference;
  
public   class  Example  extends  Applet  {
    SoftReference sr 
=   null ;
    
public   void  init()  {
      System.out.println(
" Initializing " );
    }

    
public   void  paint(Graphics g)  {
      Image im 
=  (sr  ==   null ?   null  : (Image)(sr.get());
      
if  (im  ==   null {
        System.out.println(
" Fetching image " );
        im 
=  getImage(getCodeBase(), " yundong.gif " );
        sr 
=   new  SoftReference(im);
      }

      System.out.println(
" Painting " );
      g.drawImage(im, 
25 25 this );
      g.drawString(
" 运动之美 " , 20 , 20 ); 
     im 
=   null ; 
    
/*  Clear the strong reference to the image  */
    }

  
    
public   void  start()  {
      System.out.println(
" Starting " );
    }

  
    
public   void  stop()  {
      System.out.println(
" Stopping " );
    }

  }


  
  在上面的代码中,对象image是一个图片对象,传递给一个SoftReference对象sr。其中image对象是sr的指示对象,sr中的引用域是从次引用(soft reference)到 image。
  
  Weak References分析
  
  对于一个稳定的对象,比如说线程类对象,当需要获取外部数据时,在程序中应用weak references是非常理想的。如果利用引用队列创建了某一线程的weak reference,那么当线程不再具有强获取能力时,应用程序得到通知,根据此通知,应用程序才能执行相关数据对象的清除工作。
  
  当内存管理器未发现strong references 和 soft references 时,我们称对象具有弱获取能力,即在到达该对象的路径中至少包含一个weak reference。程序中weak references被清除一段时间后,弱获取对象被收尾器收集。由此也可以看出,soft reference和weak reference之间的区别在于,应用soft reference时,内存管理器利用算法决定是否创建弱获取对象,而应用weak reference时,内存管理器必须创建次获取对象。
  
  引用对象链
  
  当到达某一对象的路径中含有多个引用对象时,就构成了引用对象链。内存管理器按照由强到弱的顺序处理引用对象,具体处理步骤包括:Soft references、 Weak references、Finalization、Phantom references和创建对象五个部分。
  
  当内存管理器未发现前三种对象引用时,我们称对象具有虚获取能力,即在到达该对象的路径中至少包含一个phantom reference。虚引用对象直接被收尾器收集,而不被重新创建。当内存管理器发现只有phantom references时,对象就将处于等候phantom reference状态,应用程序向引用队列发出通知,然后对虚引用对象调用clear()方法,将其引用域设置为null,最后对不可获取对象执行收集清除处理任务。
  
  通常,对象所具有的获取能力与引用对象集合直接路径中的最弱连接者相同。据此可以看出:
  
  图2(a)中,虚引用对象具有强获取能力,其它对象均具虚获取能力;
  
  (b)中虚引用对象和弱引用对象均具强获取能力,故次引用对象和对象集合具有若获取能力;
  
  (c)中虚引用对象、弱引用对象和次引用对象均具强获取能力,那么对象集合则具次获取能力。
   
  图2 引用对象链
  小结
  ● 引用对象API是Java2平台中的特色之一。
  
  ● 在程序中使用引用对象API不但可以在一定程度上控制内存管理器,实现内存自动管理,还可以提高程序的稳定性和安全性。
  
  ● 引用对象链中各个对象的获取能力与整个链相关。


只有注册用户登录后才能发表评论。


网站导航: