<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Fantasy's World

    世界的小世界,我的大世界^_^

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      6 Posts :: 0 Stories :: 16 Comments :: 0 Trackbacks

    2005年11月1日 #

    首先看看我寫的一個小程序:

    public class TestTry extends Exception
    {
     static boolean f=false;
     static int sum=0;
     static int created=0;
     static int i=0;
     TestTry()
     {
      i=created++;
      if(created>=299) f=true;
      }
     public void finalize()
     {
      sum++;
      }
     public static void main(String[] args)
     {
      while(!TestTry.f)
      {
       try{
        throw new TestTry();
        }catch(Exception e){}
        finally{
         System.out.println("Creat "+TestTry.i+" TestTry, "+TestTry.sum+" has been finalized!");
         }
        }
      //System.out.println("Creat "+TestTry.created+" TestTry, "+TestTry.sum+" has been finalized!"); 
      }
     }

    這個是我在測試在try語句拋出異常后,在try語句中建立的對象是否會調用自身的終止函數時發現的,這里有個奇怪的現象在if(created>=299) f=true;這條語句中,如果把條件created>=299改為>=比299更大的數,你會發現System.out.println("Creat "+TestTry.i+" TestTry, "+TestTry.sum+" has been finalized!");這條語句的輸出的結果并不是你預想的那樣(輸出判斷的數字+1的行數),而只是顯示最后的三百行。那么在這之前拋出的異常上哪里去了呢?難道說Java只處理最后拋出的三百的異常么?
    posted @ 2005-12-29 18:21 FinalFantasy 閱讀(365) | 評論 (0)編輯 收藏

    這個文檔是老師給我們看的,看了之后收獲不少,帖出來讓大家也看看:)

    引言

    Java的堆是一個運行時數據區,類的實例(對象)從中分配空間。Java虛擬機(JVM)的堆中儲存著正在運行的應用程序所建立的所有對象,這些對象通過newnewarrayanewarraymultianewarray等指令建立,但是它們不需要程序代碼來顯式地釋放。一般來說,堆的是由垃圾回收 來負責的,盡管JVM規范并不要求特殊的垃圾回收技術,甚至根本就不需要垃圾回收,但是由于內存的有限性,JVM在實現的時候都有一個由垃圾回收所管理的堆。垃圾回收是一種動態存儲管理技術,它自動地釋放不再被程序引用的對象,按照特定的垃圾收集算法來實現資源自動回收的功能。

    垃圾收集的意義

    C++中,對象所占的內存在程序結束運行之前一直被占用,在明確釋放之前不能分配給其它對象;而在Java中,當沒有對象引用指向原先分配給某個對象的內存時,該內存便成為垃圾。JVM的一個系統級線程會自動釋放該內存塊。垃圾收集意味著程序不再需要的對象是"無用信息",這些信息將被丟棄。當一個對象不再被引用的時候,內存回收它占領的空間,以便空間被后來的新對象使用。事實上,除了釋放沒用的對象,垃圾收集也可以清除內存記錄碎片。由于創建對象和垃圾收集器釋放丟棄對象所占的內存空間,內存會出現碎片。碎片是分配給對象的內存塊之間的空閑內存洞。碎片整理將所占用的堆內存移到堆的一端,JVM將整理出的內存分配給新的對象。

    垃圾收集能自動釋放內存空間,減輕編程的負擔。這使Java 虛擬機具有一些優點。首先,它能使編程效率提高。在沒有垃圾收集機制的時候,可能要花許多時間來解決一個難懂的存儲器問題。在用Java語言編程的時候,靠垃圾收集機制可大大縮短時間。其次是它保護程序的完整性, 垃圾收集是Java語言安全性策略的一個重要部份。

    垃圾收集的一個潛在的缺點是它的開銷影響程序性能。Java虛擬機必須追蹤運行程序中有用的對象, 而且最終釋放沒用的對象。這一個過程需要花費處理器的時間。其次垃圾收集算法的不完備性,早先采用的某些垃圾收集算法就不能保證100%收集到所有的廢棄內存。當然隨著垃圾收集算法的不斷改進以及軟硬件運行效率的不斷提升,這些問題都可以迎刃而解。

    垃圾收集的算法分析

    Java語言規范沒有明確地說明JVM使用哪種垃圾回收算法,但是任何一種垃圾收集算法一般要做2件基本的事情:(1)發現無用信息對象;(2)回收被無用對象占用的內存空間,使該空間可被程序再次使用。

    大多數垃圾回收算法使用了根集(root set)這個概念;所謂根集就量正在執行的Java程序可以訪問的引用變量的集合(包括局部變量、參數、類變量),程序可以使用引用變量訪問對象的屬性和調用對象的方法。垃圾收集首選需要確定從根開始哪些是可達的和哪些是不可達的,從根集可達的對象都是活動對象,它們不能作為垃圾被回收,這也包括從根集間接可達的對象。而根集通過任意路徑不可達的對象符合垃圾收集的條件,應該被回收。下面介紹幾個常用的算法。

    1、  引用計數法(Reference Counting Collector)

    引用計數法是唯一沒有使用根集的垃圾回收的法,該算法使用引用計數器來區分存活對象和不再使用的對象。一般來說,堆中的每個對象對應一個引用計數器。當每一次創建一個對象并賦給一個變量時,引用計數器置為1。當對象被賦給任意變量時,引用計數器每次加1當對象出了作用域后(該對象丟棄不再使用),引用計數器減1,一旦引用計數器為0,對象就滿足了垃圾收集的條件。

    基于引用計數器的垃圾收集器運行較快,不會長時間中斷程序執行,適宜地必須 實時運行的程序。但引用計數器增加了程序執行的開銷,因為每次對象賦給新的變量,計數器加1,而每次現有對象出了作用域生,計數器減1

    2tracing算法(Tracing Collector)

    tracing算法是為了解決引用計數法的問題而提出,它使用了根集的概念。基于tracing算法的垃圾收集器從根集開始掃描,識別出哪些對象可達,哪些對象不可達,并用某種方式標記可達對象,例如對每個可達對象設置一個或多個位。在掃描識別過程中,基于tracing算法的垃圾收集也稱為標記和清除(mark-and-sweep)垃圾收集器.

    3compacting算法(Compacting Collector)

    為了解決堆碎片問題,基于tracing的垃圾回收吸收了Compacting算法的思想,在清除的過程中,算法將所有的對象移到堆的一端,堆的另一端就變成了一個相鄰的空閑內存區,收集器會對它移動的所有對象的所有引用進行更新,使得這些引用在新的位置能識別原來 的對象。在基于Compacting算法的收集器的實現中,一般增加句柄和句柄表。  

    4copying算法(Coping Collector)

    該算法的提出是為了克服句柄的開銷和解決堆碎片的垃圾回收。它開始時把堆分成 一個對象 面和多個空閑面, 程序從對象面為對象分配空間,當對象滿了,基于coping算法的垃圾 收集就從根集中掃描活動對象,并將每個 活動對象復制到空閑面(使得活動對象所占的內存之間沒有空閑洞),這樣空閑面變成了對象面,原來的對象面變成了空閑面,程序會在新的對象面中分配內存。

    一種典型的基于coping算法的垃圾回收是stop-and-copy算法,它將堆分成對象面和空閑區域面,在對象面與空閑區域面的切換過程中,程序暫停執行。

    5generation算法(Generational Collector)
      stop-and-copy垃圾收集器的一個缺陷是收集器必須復制所有的活動對象,這增加了程序等待時間,這是coping算法低效的原因。在程序設計中有這樣的規律:多數對象存在的時間比較短,少數的存在時間比較長。因此,generation算法將堆分成兩個或多個,每個子堆作為對象的一代(generation)。由于多數對象存在的時間比較短,隨著程序丟棄不使用的對象,垃圾收集器將從最年輕的子堆中收集這些對象。在分代式的垃圾收集器運行后,上次運行存活下來的對象移到下一最高代的子堆中,由于老一代的子堆不會經常被回收,因而節省了時間。

    6adaptive算法(Adaptive Collector)

    在特定的情況下,一些垃圾收集算法會優于其它算法。基于Adaptive算法的垃圾收集器就是監控當前堆的使用情況,并將選擇適當算法的垃圾收集器。

    透視Java垃圾回收

    1、命令行參數透視垃圾收集器的運行

    2、使用System.gc()可以不管JVM使用的是哪一種垃圾回收的算法,都可以請求Java的垃圾回收。在命令行中有一個參數-verbosegc可以查看Java使用的堆內存的情況,它的格式如下:

    java -verbosegc classfile

      可以看個例子:

    class TestGC
    {
     public static void main(String[] args)
     {
      new TestGC();
      System.gc();
      System.runFinalization();
     }
    }


      在這個例子中,一個新的對象被創建,由于它沒有使用,所以該對象迅速地變為可達,程序編譯后,執行命令: java -verbosegc TestGC 后結果為:

    [Full GC 168K->97K(1984K), 0.0253873 secs]

      機器的環境為,Windows 2000 + JDK1.3.1,箭頭前后的數據168K97K分別表示垃圾收集GC前后所有存活對象使用的內存容量,說明有168K-97K=71K的對象容量被回收,括號內的數據1984K為堆內存的總容量,收集所需要的時間是0.0253873秒(這個時間在每次執行的時候會有所不同)。

      2finalize方法透視垃圾收集器的運行

      在JVM垃圾收集器收集一個對象之前 ,一般要求程序調用適當的方法釋放資源,但在沒有明確釋放資源的情況下,Java提供了缺省機制來終止化該對象心釋放資源,這個方法就是finalize()。它的原型為:

    protected void finalize() throws Throwable

      在finalize()方法返回之后,對象消失,垃圾收集開始執行。原型中的throws Throwable表示它可以拋出任何類型的異常。

      之所以要使用finalize(),是由于有時需要采取與Java的普通方法不同的一種方法,通過分配內存來做一些具有C風格的事情。這主要可以通過"固有方法"來進行,它是從Java里調用非Java方法的一種方式。CC++是目前唯一獲得固有方法支持的語言。但由于它們能調用通過其他語言編寫的子程序,所以能夠有效地調用任何東西。在非Java代碼內部,也許能調用Cmalloc()系列函數,用它分配存儲空間。而且除非調用了free(),否則存儲空間不會得到釋放,從而造成內存"漏洞"的出現。當然,free()是一個CC++函數,所以我們需要在finalize()內部的一個固有方法中調用它。也就是說我們不能過多地使用finalize(),它并不是進行普通清除工作的理想場所。

      在普通的清除工作中,為清除一個對象,那個對象的用戶必須在希望進行清除的地點調用一個清除方法。這與C++"破壞器"的概念稍有抵觸。在C++中,所有對象都會破壞(清除)。或者換句話說,所有對象都"應該"破壞。若將C++對象創建成一個本地對象,比如在堆棧中創建(在Java中是不可能的),那么清除或破壞工作就會在"結束花括號"所代表的、創建這個對象的作用域的末尾進行。若對象是用new創建的(類似于Java),那么當程序員調用C++delete命令時(Java沒有這個命令),就會調用相應的破壞器。若程序員忘記了,那么永遠不會調用破壞器,我們最終得到的將是一個內存"漏洞",另外還包括對象的其他部分永遠不會得到清除。

      相反,Java不允許我們創建本地(局部)對象--無論如何都要使用new。但在Java中,沒有"delete"命令來釋放對象,因為垃圾收集器會幫助我們自動釋放存儲空間。所以如果站在比較簡化的立場,我們可以說正是由于存在垃圾收集機制,所以Java沒有破壞器。然而,隨著以后學習的深入,就會知道垃圾收集器的存在并不能完全消除對破壞器的需要,或者說不能消除對破壞器代表的那種機制的需要(而且絕對不能直接調用finalize(),所以應盡量避免用它)。若希望執行除釋放存儲空間之外的其他某種形式的清除工作,仍然必須調用Java中的一個方法。它等價于C++的破壞器,只是沒后者方便。

      下面這個例子向大家展示了垃圾收集所經歷的過程,并對前面的陳述進行了總結。

    class Chair {
     static boolean gcrun = false;
     static boolean f = false;
     static int created = 0;
     static int finalized = 0;
     int i;
     Chair() {
      i = ++created;
      if(created == 47)
       System.out.println("Created 47");
     }
     protected void finalize() {
      if(!gcrun) {
       gcrun = true;
       System.out.println("Beginning to finalize after " + created + " Chairs have been created");
      }
      if(i == 47) {
       System.out.println("Finalizing Chair #47, " +"Setting flag to stop Chair creation");
       f = true;
      }
      finalized++;
      if(finalized >= created)
       System.out.println("All " + finalized + " finalized");
     }
    }

    public class Garbage {
     public static void main(String[] args) {
      if(args.length == 0) {
       System.err.println("Usage: \n" + "java Garbage before\n or:\n" + "java Garbage after");
       return;
      }
      while(!Chair.f) {
       new Chair();
       new String("To take up space");
      }
      System.out.println("After all Chairs have been created:\n" + "total created = " + Chair.created +
    ", total finalized = " + Chair.finalized);
      if(args[0].equals("before")) {
        System.out.println("gc():");
        System.gc();
        System.out.println("runFinalization():");
        System.runFinalization();
      }
      System.out.println("bye!");
      if(args[0].equals("after"))
       System.runFinalizersOnExit(true);
     }
    }


      上面這個程序創建了許多Chair對象,而且在垃圾收集器開始運行后的某些時候,程序會停止創建Chair。由于垃圾收集器可能在任何時間運行,所以我們不能準確知道它在何時啟動。因此,程序用一個名為gcrun的標記來指出垃圾收集器是否已經開始運行。利用第二個標記fChair可告訴main()它應停止對象的生成。這兩個標記都是在finalize()內部設置的,它調用于垃圾收集期間。另兩個static變量--created以及finalized--分別用于跟蹤已創建的對象數量以及垃圾收集器已進行完收尾工作的對象數量。最后,每個Chair都有它自己的(非staticint i,所以能跟蹤了解它具體的編號是多少。編號為47Chair進行完收尾工作后,標記會設為true,最終結束Chair對象的創建過程。(關于這個例子的更具體的分析和說明請參看《Java編程思想》的第四章)

      關于垃圾收集的幾點補充

      經過上述的說明,可以發現垃圾回收有以下的幾個特點:

      (1)垃圾收集發生的不可預知性:由于實現了不同的垃圾收集算法和采用了不同的收集機制,所以它有可能是定時發生,有可能是當出現系統空閑CPU資源時發生,也有可能是和原始的垃圾收集一樣,等到內存消耗出現極限時發生,這與垃圾收集器的選擇和具體的設置都有關系。

      (2)垃圾收集的精確性:主要包括2 個方面:(a)垃圾收集器能夠精確標記活著的對象;(b)垃圾收集器能夠精確地定位對象之間的引用關系。前者是完全地回收所有廢棄對象的前提,否則就可能造成內存泄漏。而后者則是實現歸并和復制等算法的必要條件。所有不可達對象都能夠可靠地得到回收,所有對象都能夠重新分配,允許對象的復制和對象內存的縮并,這樣就有效地防止內存的支離破碎。(3)現在有許多種不同的垃圾收集器,每種有其算法且其表現各異,既有當垃圾收集開始時就停止應用程序的運行,又有當垃圾收集開始時也允許應用程序的線程運行,還有在同一時間垃圾收集多線程運行。

      (4)垃圾收集的實現和具體的JVM 以及JVM的內存模型有非常緊密的關系。不同的JVM 可能采用不同的垃圾收集,而JVM 的內存模型決定著該JVM可以采用哪些類型垃圾收集。現在,HotSpot 系列JVM中的內存系統都采用先進的面向對象的框架設計,這使得該系列JVM都可以采用最先進的垃圾收集。

      (5)隨著技術的發展,現代垃圾收集技術提供許多可選的垃圾收集器,而且在配置每種收集器的時候又可以設置不同的參數,這就使得根據不同的應用環境獲得最優的應用性能成為可能。

      針對以上特點,我們在使用的時候要注意:

      (1)不要試圖去假定垃圾收集發生的時間,這一切都是未知的。比如,方法中的一個臨時對象在方法調用完畢后就變成了無用對象,這個時候它的內存就可以被釋放。

      (2Java中提供了一些和垃圾收集打交道的類,而且提供了一種強行執行垃圾收集的方法--調用System.gc(),但這同樣是個不確定的方法。Java 中并不保證每次調用該方法就一定能夠啟動垃圾收集,它只不過會向JVM發出這樣一個申請,到底是否真正執行垃圾收集,一切都是個未知數。

      (3)挑選適合自己的垃圾收集器。一般來說,如果系統沒有特殊和苛刻的性能要求,可以采用JVM的缺省選項。否則可以考慮使用有針對性的垃圾收集器,比如增量收集器就比較適合實時性要求較高的系統之中。系統具有較高的配置,有比較多的閑置資源,可以考慮使用并行標記/清除收集器。

      (4)關鍵的也是難把握的問題是內存泄漏。良好的編程習慣和嚴謹的編程態度永遠是最重要的,不要讓自己的一個小錯誤導致內存出現大漏洞。

      (5)盡早釋放無用對象的引用。大多數程序員在使用臨時變量的時候,都是讓引用變量在退出活動域(scope)后,自動設置為null,暗示垃圾收集器來收集該對象,還必須注意該引用的對象是否被監聽,如果有,則要去掉監聽器,然后再賦空值。

      結束語

      一般來說,Java開發人員可以不重視JVM中堆內存的分配和垃圾處理收集,但是,充分理解Java的這一特性可以讓我們更有效地利用資源。同時要注意finalize()方法是Java的缺省機制,有時為確保對象資源的明確釋放,可以編寫自己的finalize方法。

     

     

     

    posted @ 2005-12-26 17:46 FinalFantasy 閱讀(1251) | 評論 (2)編輯 收藏

    Problem Statement

    You are given a String[] cityMap representing the layout of a city. The city consists of blocks. The first element of cityMap represents the first row of blocks, etc. A 'B' character indicates a location where there is a bus stop. There will be exactly one 'X' character, indicating your location. All other characters will be '.'. You are also given an int walkingDistance, which is the maximum distance you are willing to walk to a bus stop. The distance should be calculated as the number of blocks vertically plus the number of blocks horizontally. Return the number of bus stops that are within walking distance of your current location.

    Definition

    Class:BusStops
    Method:countStops
    Parameters:String[], int
    Returns:int
    Method signature:int countStops(String[] cityMap, int walkingDistance)
    (be sure your method is public)

    Constraints

    -cityMap will contain between 1 and 50 elements, inclusive.
    -Each element of cityMap will contain between 1 and 50 characters, inclusive.
    -Each element of cityMap will contain the same number of characters.
    -Each character of each element of cityMap will be 'B', 'X', or '.'.
    -There will be exactly one 'X' character in cityMap.
    -walkingDistance will be between 1 and 100, inclusive.

    Examples

    0)

    {"...B.",
     ".....",
     "..X.B",
     ".....",
     "B...."}
    3
    Returns: 2
    You can reach the bus stop at the top (3 units away), or on the right (2 units away). The one in the lower left is 4 units away, which is too far.

    1)

    {"B.B..",
     ".....",
     "B....",
     ".....",
     "....X"}
    8
    Returns: 3
    A distance of 8 can get us anywhere on the map, so we can reach all 3 bus stops.

    2)

    {"BBBBB",
     "BB.BB",
     "B.X.B",
     "BB.BB",
     "BBBBB"}
    1
    Returns: 0
    Plenty of bus stops, but unfortunately we cannot reach any of them.

    3)

    {"B..B..",
     ".B...B",
     "..B...",
     "..B.X.",
     "B.B.B.",
     ".B.B.B"}
    3
    Returns: 7


    說實話我覺得這一題沒啥意思,超簡單,首先先確定X的位置,再用遍歷數組找B的位置,再求相減的絕對值然后判斷是否超出給出的最大距離就行了。相對這題PlayCars卻很有意思,到現在我也沒想出除了窮舉以外的一個更好的算法,因為我覺得窮舉可能會超時。有哪位有其它的辦法的話,請告訴我,大家探討一下,謝謝。好了,不廢話了,下面是這題的答案:

    public class BusStops {
     public static void main(String[] arg){
      BusStops total = new BusStops();
      
        System.out.println(total.countStops({"...B.",".....","..X.B",".....","B...."},3));
     }
     
     public int countStops(String[] cityMap, int walkingDistance){
      int sum= 0;
      int locationX = -1;
      int locationY = -1;
      for(int i=0;i<cityMap.length;i++){
       for(int j=0;j<cityMap[i].length();j++){
        if(cityMap[i].charAt(j)=='X'){
         locationX = i;
         locationY = j;
        }
       }
      }
      for(int i=0;i<cityMap.length;i++){
       for(int j=0;j<cityMap[i].length();j++){
        if(cityMap[i].charAt(j)=='B' && (Math.abs(locationX - i) + Math.abs(locationY - j)<=walkingDistance))
         sum++;
       }
      }
      return sum;
     }
    }
    posted @ 2005-12-21 18:24 FinalFantasy 閱讀(664) | 評論 (1)編輯 收藏

    Problem Statement

     

        

    When a stone is thrown across water, sometimes it will land on the water and bounce rather than falling in right away. Suppose that a stone is thrown a distance of n. On each successive bounce it will travel half the distance as the previous bounce (rounded down to the nearest integer). When it can not travel any further, it falls into the water. If, at any point, the stone lands on an obstruction rather than water, it will not bounce, but will simply deflect and fall into the water. Please look at the figure for further clarification (with black, red and green cells representing banks, obstructions and free water respectively). So, if the stone is thrown a distance 7, it will bounce and travel a distance of 3, then finally a distance of 1, having travelled a total distance of 11 (the green path in the figure). If a stone is thrown a distance of 8, it will reach the opposite bank, and if thrown at distances of 2 or 6 it will hit an obstruction during its travel. These are the three red paths in the figure.



    You are given a String water. An 'X' represents an obstruction, while a '.' represents water free from obstruction. You are to return an int representing the maximum distance a stone can travel and finally fall in the water, without hitting any obstructions, and without reaching the opposite bank (going beyond the end of the string). You may choose any initial distance for the throw, which starts from the left side of the string. A distance of 1 is the first character of the string, etc. If no initial throw will result in the stone landing in the water without hitting an obstruction, return 0.

    Definition

        

    Class:

    SkipStones

    Method:

    maxDistance

    Parameters:

    String

    Returns:

    int

    Method signature:

    int maxDistance(String water)

    (be sure your method is public)

        

     

     

     

    Notes

    -

    Obstructions are at water level, so the stone will not hit any obstructions while it's in the air.

    Constraints

    -

    water will contain between 1 and 50 elements, inclusive.

    -

    Each element of water will contain between 1 and 50 characters, inclusive.

    -

    Each character of each element of water will be 'X' or '.'.

    Examples

    0)

     

        

    "..X.....X..."

    Returns: 11

    This is the example from the problem statement.

    1)

     

        

    "...X..."

    Returns: 3

    If it weren't for the obstruction, we could start with a throw of distance 4, and go a total of 7. But, the best we can do is to throw the stone a distance of 2, and have it skip a distance of 1.

    2)

     

        

    "....X....X...XXXX.X....."

    Returns: 22

    12 + 6 + 3 + 1 = 22, is the best case.

    3)

     

        

    "XXXXXXX.XXX.X.."

    Returns: 15

    Here, an initial throw of 8 is the only way to avoid hitting an obstruction. Notice that the stone finally falls in the water just before reaching the opposite bank.

     

     


    這次的題目可以說并不是太難,也許很多人被全英文的題目給難住了,其實并不應該。像我這個還沒過CET4的人都能看得懂,何況是大家呢:)好了,廢話不多說了,下面是我寫的答案:

    public class SkipStones
    {
     public int sum;
     public int total;
     public int maxDistance(String water)
     {
      for(int i=water.length();i>0;i--)
      {
       total=0;
       sum=0;
       int j=i;
       do
       {
        sum+=j;
        j/=2;
        }while(j!=0);
       if(sum>water.length()) continue;
       else
       {
        j=i;
        int b=j-1;
        while(j!=0)
        {
         if(water.charAt(b)=='X') break;
         else
         {
          total+=j;
          j/=2;
          b+=j;
          }
         }
        }
        if(total==sum) break;
       }
       if(total==sum) return sum;
       else return 0;
      }
      
      
     public static void main(String[] args)
     {
      SkipStones a=new SkipStones();
      System.out.println("The maxdistance is "+a.maxDistance("..X.....X..."));
      }
     }
    posted @ 2005-12-14 16:32 FinalFantasy 閱讀(1671) | 評論 (5)編輯 收藏

    《thinking in java》中一段代碼剖析

    程序代碼

    //chapter03:Garbage.java

    // Demonstration of the garbage

    // collector and finalization

    class Chair {

      static boolean gcrun = false;

      static boolean f = false;

      static int created = 0;

      static int finalized = 0;

      int i;

      Chair() {

        i = ++created;

        if(created == 47)

          System.out.println("Created 47");

      }

      public void finalize() {

        if(!gcrun) {

          // The first time finalize() is called:

          gcrun = true;

          System.out.println(

            "Beginning to finalize after " +

            created + " Chairs have been created");

        }

        if(i == 47) {

          System.out.println(

            "Finalizing Chair #47, " +

            "Setting flag to stop Chair creation");

          f = true;

        }

        finalized++;

        if(finalized >= created)

          System.out.println(

            "All " + finalized + " finalized");

      }

    }

    public class Garbage {

      public static void main(String[] args) {

        // As long as the flag hasn't been set,

        // make Chairs and Strings:

        while(!Chair.f) {

          new Chair();

          new String("To take up space");

        }

        System.out.println(

          "After all Chairs have been created:\n" +

          "total created = " + Chair.created +

          ", total finalized = " + Chair.finalized);

        // Optional arguments force garbage

        // collection & finalization:

        if(args.length > 0) {

          if(args[0].equals("gc") &line;&line;

             args[0].equals("all")) {

            System.out.println("gc():");

            System.gc();

          }

          if(args[0].equals("finalize") &line;&line;

             args[0].equals("all")) {

            System.out.println("runFinalization():");

            System.runFinalization();

          }

        }

        System.out.println("bye!");

      }

    } ///:~為什么執行java Garbage gc以后,當所有對象創建完(比如8000個),這時只清除了2000個(不定),應該只能創建47個對象啊

    分析:

    首先,在一個循環當中創建對象,并且只是創建,而不引用,也就是說這個對象會自動的被系統當作垃圾處理掉。但請注意,finalize()方法并不是立刻就會執行的,執行的時間完全由系統來決定。所以很有可能的情況是已經創建了20000個對象,才開始其中的某一個對象的清除工作(這可能和時間或者系統內容的占用有關)。看finalize()方法中的一段代碼:

        if (!gcrun) {

            gcrun = true;

            System.out.println(

                "\nBeginning to finalize after" + created + "Chairs have been created\nat ");

         }

    就會出現這樣的結果:

    Beginning to finalize after 25038 Chairs have been created

    這時對象的創建過程仍在繼續(因為已經Finalize的對象還不滿47個,Chair.f還是false)。所以Chair.created會繼續增加。

    直到有47個對象被清除了,Chair.f被置成true了,創建對象的循環才結束。看main方法中的一段代碼:

        System.out.println(

            "\nAfter all chairs have been created:\n"

                + "total created ="

                + Chair.created

                + ",total finalized ="

                + Chair.finalized+"\n");

    如上所說,Chair.created是不斷增加的,而在這段代碼執行之前,又會有N個對象被釋放掉了,所以finalized也增加了。

    結果可能是這樣的:

    total created =29096,total finalized =73

    其實這一過程和使用的JVM有很大關系,執行結果可能會很不相同。但有一點是可以肯定的,那就是我們無法確定JVM什么時候做對象的清除工作(這也是Thinking in java中這段代碼的想要說明的),可能會在這個對象剛剛無用的時候就清除掉了,也可能滯后幾秒,甚至永遠不清除。

    結論:

    不能指望finalize()方法能穩定的工作,尤其不能依靠它來做文件的關閉等操作,由于finalize()的不確定性,往往得不到你想要的結果。事實上我們只需要知道所有無用的對象,JVM會自己清除就夠了。省點心思去睡覺豈不是更好的一件事情 :)

    posted @ 2005-11-01 13:05 FinalFantasy 閱讀(817) | 評論 (2)編輯 收藏

    主站蜘蛛池模板: 成人午夜性A级毛片免费| 永久在线免费观看| 国产成人免费高清在线观看| 亚洲深深色噜噜狠狠网站| 97在线观看永久免费视频| 亚洲免费二区三区| 国内大片在线免费看| 亚洲人成网站免费播放| 国产猛烈高潮尖叫视频免费| 亚洲日韩在线中文字幕综合 | 亚洲综合无码一区二区三区| 中文字幕成人免费视频| 亚洲欧洲日韩极速播放| 免费看a级黄色片| 夜夜爽妓女8888视频免费观看| 精品国产亚洲一区二区在线观看| 两个人看的www免费| 2022年亚洲午夜一区二区福利 | 国产在线a不卡免费视频| 特级毛片全部免费播放a一级| 国产成人精品日本亚洲专区| 免费毛片在线看不用播放器| 亚洲高清日韩精品第一区| 67194成是人免费无码| 国产亚洲情侣久久精品| 亚洲情XO亚洲色XO无码| 精品福利一区二区三区免费视频| 亚洲午夜在线播放| 亚洲高清成人一区二区三区| 久久国产乱子精品免费女| 亚洲AV无码国产精品色| 亚洲精品高清在线| 69影院毛片免费观看视频在线| 亚洲人成人伊人成综合网无码| 亚洲人成色77777在线观看大| 久久国产乱子伦精品免费不卡| 亚洲精品久久无码av片俺去也| 亚洲色欲色欲www在线丝| 毛片a级毛片免费观看免下载 | 免费人成视频在线播放| 亚洲午夜精品久久久久久人妖|