posts - 32, comments - 153, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          [轉(zhuǎn)]解析Java對象引用與JVM自動內(nèi)存管理

          Posted on 2006-11-29 14:08 Zou Ang 閱讀(454) 評論(0)  編輯  收藏 所屬分類:

          Java基礎(chǔ)知識,打好基礎(chǔ)才能更好地學(xué)習(xí)!
          原帖地址:http://www.linuxmine.com/44702.html
          對象引用應(yīng)用程序設(shè)計(jì)接口是JDKTM1.2中新定義的。該應(yīng)用程序設(shè)計(jì)接口允許應(yīng)用程序以對象引用的方式與JVM的內(nèi)存管理器進(jìn)行交互。當(dāng)應(yīng)用程序需管理大量內(nèi)存對象或者在新的Java對象創(chuàng)建之前需刪除原有對象時,Java對象引用應(yīng)用程序設(shè)計(jì)接口具有相當(dāng)大的用途,例如:
            
            ● 基于Web的應(yīng)用程序常常要求顯示大量圖片,當(dāng)用戶離開某一Web頁時,往往不能確定是否能夠順利的返回。在這種程序中,應(yīng)用Java對象引用API可以創(chuàng)建這樣一個環(huán)境,即當(dāng)堆內(nèi)存以最小程度運(yùn)行時,內(nèi)存管理器創(chuàng)建對象。當(dāng)用戶返回時,應(yīng)用程序就會重新載入已經(jīng)創(chuàng)建的圖片。
            
            ● 應(yīng)用對象引用隊(duì)列可以創(chuàng)建這樣一個環(huán)境,當(dāng)通過對象引用獲得某一對象時,應(yīng)用程序得到通知。然后,應(yīng)用程序就可以對相關(guān)對象進(jìn)行清除操作,同時使這些對象在內(nèi)存管理器中合法化。
            
            內(nèi)存管理器的工作機(jī)制
            
            下面將首先介紹未嵌入引用對象時內(nèi)存管理器的工作機(jī)制,然后討論引用對象加入之后Java堆發(fā)生的變化。
            
            內(nèi)存管理器的作用就是識別程序中不再使用的對象,并且回收其內(nèi)存。
            
            一個Java應(yīng)用程序由一系列線程組成,每個線程執(zhí)行一系列方法,而每個方法通過參數(shù)或局部變量來引用對象。這些引用屬于引用集合中的一部分,直接進(jìn)入應(yīng)用程序。另外,引用集合中還包括類庫中定義的靜態(tài)引用變量,以及通過Java本地接口(JNI)API獲得的引用。引用集合中的所有引用對象都可以被當(dāng)前應(yīng)用程序獲取,而不必被回收。同樣地,這些對象可能包含對其它對象的引用,也可以被應(yīng)用程序獲取,依此類推。Java堆中的其它對象視為不可獲取的,而所有這些不可獲取的對象在內(nèi)存管理中也是合法的。如果一個不可獲取的對象使用finalize()方法,任務(wù)就交給了對象所調(diào)用的收尾器(finalizer)。在內(nèi)存回收期間,不具有收尾器的不可獲取對象和已經(jīng)調(diào)用收尾器的對象被簡單回收。
            
            內(nèi)存回收的算法是不斷變化的,共性的方面是從引用集合中識別可獲取的對象以及回收被其它對象占據(jù)的內(nèi)存空間。
            
            加入引用對象之后的引用與常規(guī)引用的區(qū)別在于,引用對象中的引用專門由內(nèi)存管理器來處理。引用對象封裝了其它一些對象的引用,我們稱之為指示對象。在引用對象創(chuàng)建的同時,也就定義了該引用對象的指示對象。
            
            Java對象引用
            
            圖1所示為對象引用應(yīng)用程序設(shè)計(jì)接口中定義的類層次。其中SoftReference類、WeakReference類和PhantomReference類中分別定義了三種引用對象以及相應(yīng)的三種獲取對象的能力。因此按照由強(qiáng)到弱,對象可獲取程度可劃分為如下五種類型:強(qiáng)獲取(strongly reachable)、次獲取(softly reachable)、弱獲取(weakly reachable)、虛獲取(phantomly reachable)和不可獲取(unreachable)。
             
            圖1 對象應(yīng)用類層次
            
            根據(jù)應(yīng)用程序要求,對象可以是強(qiáng)引用(strong references)、次引用(soft references)、弱引用(weak references)、虛引用(phantom references)的任意組合。為了確定對象的可獲取程度,JVM內(nèi)存管理器從引用集合出發(fā)遍尋堆中所有到對象的路徑。當(dāng)?shù)竭_(dá)某對象的任意路徑都不含有引用對象時,則稱該對象具有強(qiáng)獲取能力;當(dāng)路徑中含有一個或幾個引用對象時,根據(jù)內(nèi)存管理器所查詢的引用對象的類型分別歸為次獲取、弱獲取、虛獲取。
            
            另外,對象引用API中還定義了引用對象隊(duì)列(java.lang.ref.ReferenceQueue),這是內(nèi)存管理器對引用對象進(jìn)行管理的一種簡單數(shù)據(jù)結(jié)構(gòu)。值得注意的是,在進(jìn)行引用對象定義時,要求phantom reference對象必須產(chǎn)生于一個引用對象隊(duì)列,而soft reference和weak reference對象則無此限制,如:
            
            

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

            Soft References 應(yīng)用實(shí)例
            
            下面以在基于web的應(yīng)用程序中使用soft references為例,來說明Java對象引用與JVM的內(nèi)存管理器進(jìn)行交互的原理。
            
            當(dāng)用戶打開某一web頁時,applet代碼獲得圖片并且得到顯示。如果在代碼中同時創(chuàng)建了該圖片對象的soft references,那么當(dāng)用戶離開該web頁時,內(nèi)存管理器對圖片所分配的內(nèi)存是否回收做出選擇。當(dāng)用戶返回該web頁時,在applet代碼中使用SoftReference.get方法就會得到圖片才內(nèi)存中是否仍存在的消息。如果在內(nèi)存管理器中未創(chuàng)建該圖片,在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(
          " 運(yùn)動之美 " , 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分析
            
            對于一個穩(wěn)定的對象,比如說線程類對象,當(dāng)需要獲取外部數(shù)據(jù)時,在程序中應(yīng)用weak references是非常理想的。如果利用引用隊(duì)列創(chuàng)建了某一線程的weak reference,那么當(dāng)線程不再具有強(qiáng)獲取能力時,應(yīng)用程序得到通知,根據(jù)此通知,應(yīng)用程序才能執(zhí)行相關(guān)數(shù)據(jù)對象的清除工作。
            
            當(dāng)內(nèi)存管理器未發(fā)現(xiàn)strong references 和 soft references 時,我們稱對象具有弱獲取能力,即在到達(dá)該對象的路徑中至少包含一個weak reference。程序中weak references被清除一段時間后,弱獲取對象被收尾器收集。由此也可以看出,soft reference和weak reference之間的區(qū)別在于,應(yīng)用soft reference時,內(nèi)存管理器利用算法決定是否創(chuàng)建弱獲取對象,而應(yīng)用weak reference時,內(nèi)存管理器必須創(chuàng)建次獲取對象。
            
            引用對象鏈
            
            當(dāng)?shù)竭_(dá)某一對象的路徑中含有多個引用對象時,就構(gòu)成了引用對象鏈。內(nèi)存管理器按照由強(qiáng)到弱的順序處理引用對象,具體處理步驟包括:Soft references、 Weak references、Finalization、Phantom references和創(chuàng)建對象五個部分。
            
            當(dāng)內(nèi)存管理器未發(fā)現(xiàn)前三種對象引用時,我們稱對象具有虛獲取能力,即在到達(dá)該對象的路徑中至少包含一個phantom reference。虛引用對象直接被收尾器收集,而不被重新創(chuàng)建。當(dāng)內(nèi)存管理器發(fā)現(xiàn)只有phantom references時,對象就將處于等候phantom reference狀態(tài),應(yīng)用程序向引用隊(duì)列發(fā)出通知,然后對虛引用對象調(diào)用clear()方法,將其引用域設(shè)置為null,最后對不可獲取對象執(zhí)行收集清除處理任務(wù)。
            
            通常,對象所具有的獲取能力與引用對象集合直接路徑中的最弱連接者相同。據(jù)此可以看出:
            
            圖2(a)中,虛引用對象具有強(qiáng)獲取能力,其它對象均具虛獲取能力;
            
            (b)中虛引用對象和弱引用對象均具強(qiáng)獲取能力,故次引用對象和對象集合具有若獲取能力;
            
            (c)中虛引用對象、弱引用對象和次引用對象均具強(qiáng)獲取能力,那么對象集合則具次獲取能力。
             
            圖2 引用對象鏈
            小結(jié)
            ● 引用對象API是Java2平臺中的特色之一。
            
            ● 在程序中使用引用對象API不但可以在一定程度上控制內(nèi)存管理器,實(shí)現(xiàn)內(nèi)存自動管理,還可以提高程序的穩(wěn)定性和安全性。
            
            ● 引用對象鏈中各個對象的獲取能力與整個鏈相關(guān)。

          主站蜘蛛池模板: 广德县| 于都县| 奈曼旗| 富裕县| 江口县| 凌源市| 茌平县| 瑞昌市| 岳阳市| 扬中市| 嘉定区| 西盟| 长岭县| 改则县| 五河县| 鄂温| 潍坊市| 文化| 阳谷县| 股票| 荔浦县| 扶风县| 永泰县| 邓州市| 丁青县| 河津市| 公安县| 金堂县| 曲靖市| 晋宁县| 井研县| 云浮市| 黑水县| 寿光市| 惠东县| 将乐县| 海盐县| 昌黎县| 达尔| 梓潼县| 吉水县|