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

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

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

    Fantasy's World

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

      BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
      6 Posts :: 0 Stories :: 16 Comments :: 0 Trackbacks

    2005年10月6日 #

    首先看看我寫(xiě)的一個(gè)小程序:

    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!"); 
      }
     }

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

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

    引言

    Java的堆是一個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū),類的實(shí)例(對(duì)象)從中分配空間。Java虛擬機(jī)(JVM)的堆中儲(chǔ)存著正在運(yùn)行的應(yīng)用程序所建立的所有對(duì)象,這些對(duì)象通過(guò)newnewarrayanewarraymultianewarray等指令建立,但是它們不需要程序代碼來(lái)顯式地釋放。一般來(lái)說(shuō),堆的是由垃圾回收 來(lái)負(fù)責(zé)的,盡管JVM規(guī)范并不要求特殊的垃圾回收技術(shù),甚至根本就不需要垃圾回收,但是由于內(nèi)存的有限性,JVM在實(shí)現(xiàn)的時(shí)候都有一個(gè)由垃圾回收所管理的堆。垃圾回收是一種動(dòng)態(tài)存儲(chǔ)管理技術(shù),它自動(dòng)地釋放不再被程序引用的對(duì)象,按照特定的垃圾收集算法來(lái)實(shí)現(xiàn)資源自動(dòng)回收的功能。

    垃圾收集的意義

    C++中,對(duì)象所占的內(nèi)存在程序結(jié)束運(yùn)行之前一直被占用,在明確釋放之前不能分配給其它對(duì)象;而在Java中,當(dāng)沒(méi)有對(duì)象引用指向原先分配給某個(gè)對(duì)象的內(nèi)存時(shí),該內(nèi)存便成為垃圾。JVM的一個(gè)系統(tǒng)級(jí)線程會(huì)自動(dòng)釋放該內(nèi)存塊。垃圾收集意味著程序不再需要的對(duì)象是"無(wú)用信息",這些信息將被丟棄。當(dāng)一個(gè)對(duì)象不再被引用的時(shí)候,內(nèi)存回收它占領(lǐng)的空間,以便空間被后來(lái)的新對(duì)象使用。事實(shí)上,除了釋放沒(méi)用的對(duì)象,垃圾收集也可以清除內(nèi)存記錄碎片。由于創(chuàng)建對(duì)象和垃圾收集器釋放丟棄對(duì)象所占的內(nèi)存空間,內(nèi)存會(huì)出現(xiàn)碎片。碎片是分配給對(duì)象的內(nèi)存塊之間的空閑內(nèi)存洞。碎片整理將所占用的堆內(nèi)存移到堆的一端,JVM將整理出的內(nèi)存分配給新的對(duì)象。

    垃圾收集能自動(dòng)釋放內(nèi)存空間,減輕編程的負(fù)擔(dān)。這使Java 虛擬機(jī)具有一些優(yōu)點(diǎn)。首先,它能使編程效率提高。在沒(méi)有垃圾收集機(jī)制的時(shí)候,可能要花許多時(shí)間來(lái)解決一個(gè)難懂的存儲(chǔ)器問(wèn)題。在用Java語(yǔ)言編程的時(shí)候,靠垃圾收集機(jī)制可大大縮短時(shí)間。其次是它保護(hù)程序的完整性, 垃圾收集是Java語(yǔ)言安全性策略的一個(gè)重要部份。

    垃圾收集的一個(gè)潛在的缺點(diǎn)是它的開(kāi)銷影響程序性能。Java虛擬機(jī)必須追蹤運(yùn)行程序中有用的對(duì)象, 而且最終釋放沒(méi)用的對(duì)象。這一個(gè)過(guò)程需要花費(fèi)處理器的時(shí)間。其次垃圾收集算法的不完備性,早先采用的某些垃圾收集算法就不能保證100%收集到所有的廢棄內(nèi)存。當(dāng)然隨著垃圾收集算法的不斷改進(jìn)以及軟硬件運(yùn)行效率的不斷提升,這些問(wèn)題都可以迎刃而解。

    垃圾收集的算法分析

    Java語(yǔ)言規(guī)范沒(méi)有明確地說(shuō)明JVM使用哪種垃圾回收算法,但是任何一種垃圾收集算法一般要做2件基本的事情:(1)發(fā)現(xiàn)無(wú)用信息對(duì)象;(2)回收被無(wú)用對(duì)象占用的內(nèi)存空間,使該空間可被程序再次使用。

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

    1、  引用計(jì)數(shù)法(Reference Counting Collector)

    引用計(jì)數(shù)法是唯一沒(méi)有使用根集的垃圾回收的法,該算法使用引用計(jì)數(shù)器來(lái)區(qū)分存活對(duì)象和不再使用的對(duì)象。一般來(lái)說(shuō),堆中的每個(gè)對(duì)象對(duì)應(yīng)一個(gè)引用計(jì)數(shù)器。當(dāng)每一次創(chuàng)建一個(gè)對(duì)象并賦給一個(gè)變量時(shí),引用計(jì)數(shù)器置為1。當(dāng)對(duì)象被賦給任意變量時(shí),引用計(jì)數(shù)器每次加1當(dāng)對(duì)象出了作用域后(該對(duì)象丟棄不再使用),引用計(jì)數(shù)器減1,一旦引用計(jì)數(shù)器為0,對(duì)象就滿足了垃圾收集的條件。

    基于引用計(jì)數(shù)器的垃圾收集器運(yùn)行較快,不會(huì)長(zhǎng)時(shí)間中斷程序執(zhí)行,適宜地必須 實(shí)時(shí)運(yùn)行的程序。但引用計(jì)數(shù)器增加了程序執(zhí)行的開(kāi)銷,因?yàn)槊看螌?duì)象賦給新的變量,計(jì)數(shù)器加1,而每次現(xiàn)有對(duì)象出了作用域生,計(jì)數(shù)器減1

    2tracing算法(Tracing Collector)

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

    3compacting算法(Compacting Collector)

    為了解決堆碎片問(wèn)題,基于tracing的垃圾回收吸收了Compacting算法的思想,在清除的過(guò)程中,算法將所有的對(duì)象移到堆的一端,堆的另一端就變成了一個(gè)相鄰的空閑內(nèi)存區(qū),收集器會(huì)對(duì)它移動(dòng)的所有對(duì)象的所有引用進(jìn)行更新,使得這些引用在新的位置能識(shí)別原來(lái) 的對(duì)象。在基于Compacting算法的收集器的實(shí)現(xiàn)中,一般增加句柄和句柄表。  

    4copying算法(Coping Collector)

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

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

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

    6adaptive算法(Adaptive Collector)

    在特定的情況下,一些垃圾收集算法會(huì)優(yōu)于其它算法。基于Adaptive算法的垃圾收集器就是監(jiān)控當(dāng)前堆的使用情況,并將選擇適當(dāng)算法的垃圾收集器。

    透視Java垃圾回收

    1、命令行參數(shù)透視垃圾收集器的運(yùn)行

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

    java -verbosegc classfile

      可以看個(gè)例子:

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


      在這個(gè)例子中,一個(gè)新的對(duì)象被創(chuàng)建,由于它沒(méi)有使用,所以該對(duì)象迅速地變?yōu)榭蛇_(dá),程序編譯后,執(zhí)行命令: java -verbosegc TestGC 后結(jié)果為:

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

      機(jī)器的環(huán)境為,Windows 2000 + JDK1.3.1,箭頭前后的數(shù)據(jù)168K97K分別表示垃圾收集GC前后所有存活對(duì)象使用的內(nèi)存容量,說(shuō)明有168K-97K=71K的對(duì)象容量被回收,括號(hào)內(nèi)的數(shù)據(jù)1984K為堆內(nèi)存的總?cè)萘浚占枰臅r(shí)間是0.0253873秒(這個(gè)時(shí)間在每次執(zhí)行的時(shí)候會(huì)有所不同)。

      2finalize方法透視垃圾收集器的運(yùn)行

      在JVM垃圾收集器收集一個(gè)對(duì)象之前 ,一般要求程序調(diào)用適當(dāng)?shù)姆椒ㄡ尫刨Y源,但在沒(méi)有明確釋放資源的情況下,Java提供了缺省機(jī)制來(lái)終止化該對(duì)象心釋放資源,這個(gè)方法就是finalize()。它的原型為:

    protected void finalize() throws Throwable

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

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

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

      相反,Java不允許我們創(chuàng)建本地(局部)對(duì)象--無(wú)論如何都要使用new。但在Java中,沒(méi)有"delete"命令來(lái)釋放對(duì)象,因?yàn)槔占鲿?huì)幫助我們自動(dòng)釋放存儲(chǔ)空間。所以如果站在比較簡(jiǎn)化的立場(chǎng),我們可以說(shuō)正是由于存在垃圾收集機(jī)制,所以Java沒(méi)有破壞器。然而,隨著以后學(xué)習(xí)的深入,就會(huì)知道垃圾收集器的存在并不能完全消除對(duì)破壞器的需要,或者說(shuō)不能消除對(duì)破壞器代表的那種機(jī)制的需要(而且絕對(duì)不能直接調(diào)用finalize(),所以應(yīng)盡量避免用它)。若希望執(zhí)行除釋放存儲(chǔ)空間之外的其他某種形式的清除工作,仍然必須調(diào)用Java中的一個(gè)方法。它等價(jià)于C++的破壞器,只是沒(méi)后者方便。

      下面這個(gè)例子向大家展示了垃圾收集所經(jīng)歷的過(guò)程,并對(duì)前面的陳述進(jìn)行了總結(jié)。

    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);
     }
    }


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

      關(guān)于垃圾收集的幾點(diǎn)補(bǔ)充

      經(jīng)過(guò)上述的說(shuō)明,可以發(fā)現(xiàn)垃圾回收有以下的幾個(gè)特點(diǎn):

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

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

      (4)垃圾收集的實(shí)現(xiàn)和具體的JVM 以及JVM的內(nèi)存模型有非常緊密的關(guān)系。不同的JVM 可能采用不同的垃圾收集,而JVM 的內(nèi)存模型決定著該JVM可以采用哪些類型垃圾收集。現(xiàn)在,HotSpot 系列JVM中的內(nèi)存系統(tǒng)都采用先進(jìn)的面向?qū)ο蟮目蚣茉O(shè)計(jì),這使得該系列JVM都可以采用最先進(jìn)的垃圾收集。

      (5)隨著技術(shù)的發(fā)展,現(xiàn)代垃圾收集技術(shù)提供許多可選的垃圾收集器,而且在配置每種收集器的時(shí)候又可以設(shè)置不同的參數(shù),這就使得根據(jù)不同的應(yīng)用環(huán)境獲得最優(yōu)的應(yīng)用性能成為可能。

      針對(duì)以上特點(diǎn),我們?cè)谑褂玫臅r(shí)候要注意:

      (1)不要試圖去假定垃圾收集發(fā)生的時(shí)間,這一切都是未知的。比如,方法中的一個(gè)臨時(shí)對(duì)象在方法調(diào)用完畢后就變成了無(wú)用對(duì)象,這個(gè)時(shí)候它的內(nèi)存就可以被釋放。

      (2Java中提供了一些和垃圾收集打交道的類,而且提供了一種強(qiáng)行執(zhí)行垃圾收集的方法--調(diào)用System.gc(),但這同樣是個(gè)不確定的方法。Java 中并不保證每次調(diào)用該方法就一定能夠啟動(dòng)垃圾收集,它只不過(guò)會(huì)向JVM發(fā)出這樣一個(gè)申請(qǐng),到底是否真正執(zhí)行垃圾收集,一切都是個(gè)未知數(shù)。

      (3)挑選適合自己的垃圾收集器。一般來(lái)說(shuō),如果系統(tǒng)沒(méi)有特殊和苛刻的性能要求,可以采用JVM的缺省選項(xiàng)。否則可以考慮使用有針對(duì)性的垃圾收集器,比如增量收集器就比較適合實(shí)時(shí)性要求較高的系統(tǒng)之中。系統(tǒng)具有較高的配置,有比較多的閑置資源,可以考慮使用并行標(biāo)記/清除收集器。

      (4)關(guān)鍵的也是難把握的問(wèn)題是內(nèi)存泄漏。良好的編程習(xí)慣和嚴(yán)謹(jǐn)?shù)木幊虘B(tài)度永遠(yuǎn)是最重要的,不要讓自己的一個(gè)小錯(cuò)誤導(dǎo)致內(nèi)存出現(xiàn)大漏洞。

      (5)盡早釋放無(wú)用對(duì)象的引用。大多數(shù)程序員在使用臨時(shí)變量的時(shí)候,都是讓引用變量在退出活動(dòng)域(scope)后,自動(dòng)設(shè)置為null,暗示垃圾收集器來(lái)收集該對(duì)象,還必須注意該引用的對(duì)象是否被監(jiān)聽(tīng),如果有,則要去掉監(jiān)聽(tīng)器,然后再賦空值。

      結(jié)束語(yǔ)

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

     

     

     

    posted @ 2005-12-26 17:46 FinalFantasy 閱讀(1251) | 評(píng)論 (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


    說(shuō)實(shí)話我覺(jué)得這一題沒(méi)啥意思,超簡(jiǎn)單,首先先確定X的位置,再用遍歷數(shù)組找B的位置,再求相減的絕對(duì)值然后判斷是否超出給出的最大距離就行了。相對(duì)這題PlayCars卻很有意思,到現(xiàn)在我也沒(méi)想出除了窮舉以外的一個(gè)更好的算法,因?yàn)槲矣X(jué)得窮舉可能會(huì)超時(shí)。有哪位有其它的辦法的話,請(qǐng)告訴我,大家探討一下,謝謝。好了,不廢話了,下面是這題的答案:

    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) | 評(píng)論 (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.

     

     


    這次的題目可以說(shuō)并不是太難,也許很多人被全英文的題目給難住了,其實(shí)并不應(yīng)該。像我這個(gè)還沒(méi)過(guò)CET4的人都能看得懂,何況是大家呢:)好了,廢話不多說(shuō)了,下面是我寫(xiě)的答案:

    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) | 評(píng)論 (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!");

      }

    } ///:~為什么執(zhí)行java Garbage gc以后,當(dāng)所有對(duì)象創(chuàng)建完(比如8000個(gè)),這時(shí)只清除了2000個(gè)(不定),應(yīng)該只能創(chuàng)建47個(gè)對(duì)象啊

    分析:

    首先,在一個(gè)循環(huán)當(dāng)中創(chuàng)建對(duì)象,并且只是創(chuàng)建,而不引用,也就是說(shuō)這個(gè)對(duì)象會(huì)自動(dòng)的被系統(tǒng)當(dāng)作垃圾處理掉。但請(qǐng)注意,finalize()方法并不是立刻就會(huì)執(zhí)行的,執(zhí)行的時(shí)間完全由系統(tǒng)來(lái)決定。所以很有可能的情況是已經(jīng)創(chuàng)建了20000個(gè)對(duì)象,才開(kāi)始其中的某一個(gè)對(duì)象的清除工作(這可能和時(shí)間或者系統(tǒng)內(nèi)容的占用有關(guān))。看finalize()方法中的一段代碼:

        if (!gcrun) {

            gcrun = true;

            System.out.println(

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

         }

    就會(huì)出現(xiàn)這樣的結(jié)果:

    Beginning to finalize after 25038 Chairs have been created

    這時(shí)對(duì)象的創(chuàng)建過(guò)程仍在繼續(xù)(因?yàn)橐呀?jīng)Finalize的對(duì)象還不滿47個(gè),Chair.f還是false)。所以Chair.created會(huì)繼續(xù)增加。

    直到有47個(gè)對(duì)象被清除了,Chair.f被置成true了,創(chuàng)建對(duì)象的循環(huán)才結(jié)束。看main方法中的一段代碼:

        System.out.println(

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

                + "total created ="

                + Chair.created

                + ",total finalized ="

                + Chair.finalized+"\n");

    如上所說(shuō),Chair.created是不斷增加的,而在這段代碼執(zhí)行之前,又會(huì)有N個(gè)對(duì)象被釋放掉了,所以finalized也增加了。

    結(jié)果可能是這樣的:

    total created =29096,total finalized =73

    其實(shí)這一過(guò)程和使用的JVM有很大關(guān)系,執(zhí)行結(jié)果可能會(huì)很不相同。但有一點(diǎn)是可以肯定的,那就是我們無(wú)法確定JVM什么時(shí)候做對(duì)象的清除工作(這也是Thinking in java中這段代碼的想要說(shuō)明的),可能會(huì)在這個(gè)對(duì)象剛剛無(wú)用的時(shí)候就清除掉了,也可能滯后幾秒,甚至永遠(yuǎn)不清除。

    結(jié)論:

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

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

     

    洛陽(yáng)的天氣可真是討厭,昨天好不容易放晴了一天,今天就又下起了大雨,本來(lái)計(jì)劃好去買(mǎi)衣服的,現(xiàn)在只能泡湯了。這幾天來(lái)上網(wǎng)查了很多的資料,為了組建一個(gè)PHP、JSP、ASP的全能平臺(tái),PHP跟JSP的平臺(tái)是組建好了,可是ASP怎么樣都不行,好不容易下了個(gè)IASP裝上了,配置了之后卻老是出現(xiàn)錯(cuò)誤。哎NB怎么就不配個(gè)專業(yè)版的系統(tǒng)給我呢,這樣我就不用那么費(fèi)勁了,只要把IIS跟Apache整合起來(lái)就行了。趁著有點(diǎn)時(shí)間就把用apache組建的PHP、JSP平臺(tái)教程整理出來(lái)了,說(shuō)實(shí)話光這兩個(gè)都費(fèi)了我好多的勁呀,特別是JSP,網(wǎng)上的教程都不知道是什么年代寫(xiě)的了,幾乎都不能用了,我廢了好幾天的功夫才把這些零件給找齊,所以還特別記下了下載的地址,要下的就要趕快了!好了,廢話不多說(shuō)了,往下看吧。對(duì)了,另外再多說(shuō)一句,下面的配置是我安裝我本機(jī)的安裝地址的,如果你的安裝地址跟我的不符,那么你就要一些相應(yīng)的改進(jìn)!還有,如果一下的下載地址無(wú)效了,你可以在我這留下你的郵箱,我可以將這些東西發(fā)給你。


    前期準(zhǔn)備: 

    所需軟件列表
    1、apache_2.0.54-win32-x86-no_ssl.exe (Apache web服務(wù)器) http://apache.justdn.org/......2.0.54-win32-x86-no_ssl.exe
    2、php-5.0.5-Win32 (PHP語(yǔ)言解析器)
    4、jdk1.4.2(JAVA 語(yǔ)言環(huán)境)
    5、jakarta-tomcat-5.5.12 (Tomcat JSP解析服務(wù)器) http://mirror.vmmatrix.ne......in/apache-tomcat-5.5.12.exe
    7、mod_jk-1.2.14-apache-2.0.54.so.asc (整合Apache+Tomcat的plus) http://apache.linuxforum.......1.2.14-apache-2.0.54.so.asc(為了找這個(gè)文件都把我給找瘋了,網(wǎng)上的教程到處都說(shuō)要mod_jk_1.2.5_2.0.47.dll,可是我找了兩天死都找不到,后來(lái)到apache的官方網(wǎng)站看著生硬的EN去查才找到這么個(gè)文件,看文件名直覺(jué)就告訴我找對(duì)了,現(xiàn)在的apache不都是用so擴(kuò)展了么,而且在那個(gè)頁(yè)面也說(shuō)明了這一點(diǎn),要使用還要改名,所以在這里特別指出下載地址,讓大家少走很多的彎路)

    開(kāi)始安裝:
    一、 Apahce+PHP安裝配置 

    1、安裝apache_2.0.54-win32-x86-no_ssl.exe,為了方便把路徑改為c:\吧,其他都不用管一路next下去。
    2、安裝完成之后,apache服務(wù)自動(dòng)加載,這時(shí)打開(kāi)瀏覽器,瀏覽:http://localhost,出現(xiàn)apache歡迎頁(yè)面(這步需要將C:\apache2\htdocs目錄中的文件“index.html.en”改為“index.html”,方能顯示);如果這步出現(xiàn)異常,請(qǐng)檢查安裝源文件,重新安裝。
    3. 安裝php-5.0.5-Win32,一般下載的PHP文件為一個(gè)免安裝的壓縮包,解壓到C:\PHP就可以。 
    4. 配置PHP和Apache,使之能解析php程序。 
    PHP配置:將C:\PHP\目錄中的“php.ini-dist”改名“php.ini”,然后添加環(huán)境變量。在環(huán)境變量里的classpath中添加“.;c:\php;”,在新建一個(gè)“PHPRC”的變量,里面同樣是添加“.;c:\php;” 
    Apache配置: 
    打開(kāi)C:\apache2\conf\httpd.conf 

    httpd.conf是apache的配置文件,在此配置文件最后添加以下語(yǔ)句,用以支持php程序: 

    ScriptAlias /php/ "C:/PHP/" 

    AddType application/x-httpd-php .php3 

    AddType application/x-httpd-php .php 

    AddType application/x-httpd-php .phtml 

    Action application/x-httpd-php "/php/php.exe" 

    ok,接下來(lái)重啟Apache服務(wù)器(如果加載PHP成功,可以在Apache監(jiān)控器中看到Apache/2.0.52(win32) PHP/5.0.4)就可以測(cè)試了PHP了,用編輯器編寫(xiě)如下語(yǔ)句: 
    <?
    phpinfo(); 

    ?> 

    保存文件名為“test.php”到C:\apache2\htdocs目錄,然后打開(kāi)瀏覽器,瀏覽:http://localhost/test.php,出現(xiàn)PHP基本信息就說(shuō)明配置成功。嚴(yán)格按以上說(shuō)明安裝配置,都會(huì)一次成功。

    二、安裝JDK和Tomcat

    1. 安裝j2sdk-1_4_2-windows-i586,JDK一定要在Tomcat之前安裝,默認(rèn)安裝路徑就可以。
    2. 安裝Jakarta-Tomcat-5.5.12,默認(rèn)安裝路徑就可以。
    4.設(shè)置環(huán)境變量(桌面->我的電腦->右鍵點(diǎn)擊->選擇“屬性”->高級(jí)->環(huán)境變量),所有設(shè)置均在系統(tǒng)變量欄進(jìn)行。
    新建->變量名:JAVA_HOME
    ->變量值:C:\j2sdk1.4.2
    新建->變量名:TOMCAT_HOME
    ->變量值:C:\Program Files\Apache Software Foundation\Tomcat 5.5
    新建->變量名: PATH
    ->變量值:.;C:\j2sdk1.4.2\bin; (前面的“.;”一定要有)
    修改增加環(huán)境變量 CLASSPATH (如果沒(méi)有此變量名,則新建)
    ->增加變量值:.;C:\j2sdk1.4.2\lib\dt.jar;C:\j2sdk1.4.2\lib\tool.jar;
    C:\j2sdk1.4.2\lib\NetComponents.jar;
    C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\classes;
    C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\lib;
    C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\lib\servlet-api.jar;(前面的“.;”一定要有)

    5. 啟動(dòng)Tomcat服務(wù)器,打開(kāi)瀏覽器,瀏覽:http://localhost:8080/ ,出現(xiàn)Tomcat歡迎頁(yè)面;如果這步出現(xiàn)異常,請(qǐng)檢查安裝源文件,重新安裝。

    三、整合Apache+Tomcat服務(wù)器

    1. 復(fù)制mod_jk-1.2.14-apache-2.0.54.so.asc文件到C:\Apache2\modules目錄,并將其文件名改為mod_jk.so。
    2. Apache配置:
    C:\apahce2\conf\httpd.conf
    httpd.conf
    在此配置文件最后添加以下語(yǔ)句,用以支持jsp程序:
    LoadModule jk_module modules/mod_jk.so

    JkWorkersFile "C:/Program Files/Apache Software Foundation/Tomcat 5.5/conf/workers.properties"
    JkMount /servlet/* ajp13
    JkMount /*.jsp ajp13

    還有要在
    DirectoryIndex index.html index.html.var的后面加上default.jsp index.jsp(前面忘了說(shuō)了,支持PHP還要加上index.php default.php)

    3. 在C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\目錄下,新建文件名為“workers.properties”的文件,將如下內(nèi)容復(fù)制到新建文件workers.properties中。

    workers.properties
    # 只復(fù)制以下內(nèi)容即可:

    workers.tomcat_home=C:\Program Files\Apache Software Foundation\Tomcat 5.5
    workers.java_home=C:\j2sdk1.4.2
    ps=\
    # worker.list=ajp13
    worker.list=ajp12,ajp13

    worker.ajp12.port=8007
    worker.ajp12.host=localhost
    worker.ajp12.type=ajp12
    worker.ajp12.lbfactor=1

    worker.ajp13.port=8009
    worker.ajp13.host=localhost
    worker.ajp13.type=ajp13
    worker.ajp13.lbfactor=1

    worker.loadbalancer.type=lb

    worker.loadbalancer.balanced_workers=ajp12, ajp13
    worker.inprocess.type=jni
    worker.inprocess.class_path=$(workers.tomcat_home)$(ps)classes
    worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)jaxp.jar

    worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)parser.jar

    worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)jasper.jar

    worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)servlet.jar

    worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)webserver.jar

    worker.inprocess.class_path=$(workers.java_home)$(ps)lib$(ps)tools.jar

    worker.inprocess.cmd_line=-config

    worker.inprocess.cmd_line=$(workers.tomcat_home)/conf/jni_server.xml

    worker.inprocess.cmd_line=-home

    worker.inprocess.cmd_line=$(workers.tomcat_home)

    worker.inprocess.jvm_lib=$(workers.java_home)$(ps)jre$(ps)bin$(ps)classic$(ps)jvm.dll


    worker.inprocess.stdout=$(workers.tomcat_home)$(ps)inprocess.stdout

    worker.inprocess.stderr=$(workers.tomcat_home)$(ps)inprocess.stderr

    worker.inprocess.sysprops=tomcat.home=$(workers.tomcat_home)

    接下來(lái)重啟Tomcat和Apache服務(wù)器(必須先重啟Tomcat再重啟Apache,不然會(huì)出錯(cuò),如果加載JK成功,這個(gè)時(shí)候你可以在Apache監(jiān)控器中看到Apache/2.0.52(win32) PHP/5.0.4 mod_jk/1.2.8)就可以測(cè)試了,把Tomcat的webapps這個(gè)目錄拷貝到Apache的htdocs目錄下面,然后直接在瀏覽器地址欄輸入:http://localhost/webappshttp://localhost:8080如果顯示的頁(yè)面一樣就說(shuō)明成功了。

    剩下的就是連接MySQL了,但是本人不才一個(gè)叫mm.mysql-2.0.4-bin.jar的文件怎么也找不到,只找到了個(gè)mysql-connector-java-3.1.5-gamma-bin.jar的文件,可是我試過(guò)了一點(diǎn)用都沒(méi)有,所以連接數(shù)據(jù)庫(kù)的教程等我試驗(yàn)成功再說(shuō)拉!如果哪位高人能救救我的告訴我mm.mysql-2.0.4-bin.jar的下載地址或者告訴我IASP到底改如何配置,我真是感激不盡。


    posted @ 2005-10-06 19:28 FinalFantasy 閱讀(4318) | 評(píng)論 (6)編輯 收藏

    主站蜘蛛池模板: 国产精品亚洲二区在线观看 | 国产亚洲精aa在线看| 国产亚洲Av综合人人澡精品| a级毛片毛片免费观看久潮喷| 国产成人yy免费视频| 亚洲日本一区二区一本一道| 亚洲电影在线免费观看| 免费在线观看一区| 免费观看国产网址你懂的| 亚洲国产高清在线一区二区三区| 91大神亚洲影视在线| 最新亚洲人成网站在线观看| 亚洲免费中文字幕| 亚洲伊人久久成综合人影院| 亚洲毛片基地4455ww| 91视频免费观看| 国产gav成人免费播放视频| 亚洲视频在线免费播放| 成人午夜免费视频| 噼里啪啦电影在线观看免费高清 | 国产午夜精品久久久久免费视 | 亚洲午夜福利AV一区二区无码| 亚洲kkk4444在线观看| 国产免费网站看v片在线| 国产一级一片免费播放| 亚洲欧洲国产精品你懂的| 免费很黄无遮挡的视频毛片| 成年女人免费视频播放体验区| 亚洲AV永久青草无码精品| 污污的视频在线免费观看| 日韩精品福利片午夜免费观着| 亚洲狠狠久久综合一区77777| 一个人免费观看日本www视频| 四虎影视www四虎免费| 亚洲日韩乱码中文无码蜜桃臀| 国产在线国偷精品免费看| 国产一级一片免费播放| 亚洲日韩一中文字暮| 久久久久久曰本AV免费免费| 久久亚洲综合色一区二区三区| 高潮毛片无遮挡高清免费|