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

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

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

    Be alaways javaing...

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

    2008年12月3日


    posted @ 2008-12-16 09:37 追風(fēng)舞者 閱讀(157) | 評論 (0)編輯 收藏

    轉(zhuǎn)載自:www.tkk7.com/zhaobin
    來自BlueDavy的博客

      1. 為什么學(xué)習(xí)OSGi
      2. OSGi成為JSR291以及OSGi對Spring產(chǎn)生的影響
      3. OSGi應(yīng)用于企業(yè)應(yīng)用Step by step之持久篇
      4. SCA:企業(yè)應(yīng)用開發(fā)的利器
      5. OSGi和SCA
      6. 基于OSGi實現(xiàn)可擴展的模塊的設(shè)計
      7. OSGi in action online演講的資料【推薦】
      8. 基于OSGi搭建動態(tài)化的系統(tǒng)
      9. OSGi Extender Model啟示錄
      10. Play OSGi
      11. Bnd - Bundle Tool中文使用手冊
      12. 基于Eclipse Equinox的插件框架:TPF
      13. TPF插件管理框架功能、實現(xiàn)以及下載【推薦】
      14. 發(fā)布《OSGi實戰(zhàn)》正式版【特別推薦】
      15. 發(fā)布《OSGi進階》正式版【特別推薦】
      16. OSGi PPT For Newer【推薦】

    來自 勤勞的蜜蜂的博客

      1. OSGi介紹(一)什么是OSGi
      2. OSGi介紹(二)一個假想的實例
      3. OSGi介紹(三)OSGi service platform的體系結(jié)構(gòu)
      4. OSGi介紹(四)第一個bundle
      5. OSGi介紹(五)兩個bundle
      6. OSGi介紹(六)OSGi的service
      7. OSGi介紹(七)bundle和service(續(xù))

    來自Phrancol的博客

      1. 構(gòu)建模塊化的動態(tài)Web應(yīng)用(演示版)
      2. 開發(fā)基于Equinox/OSGI 的 Web Application (一) [譯]
      3. 開發(fā)基于Equinox/OSGI 的 Web Application (二) [譯]
      4. Spring-OSGI 1.0 M3 中文手冊(Spring Dynamic Modules Reference Guide for OSGi(tm) Service Platforms)
      5. Developing Equinox/Spring-osgi/Spring Framework Web Application Part 1 - 顯示首頁【推薦】
      6. Developing Equinox/Spring-osgi/Spring Framework Web Application Part 2 - 使用Spring-OSGI
      7. Developing Equinox/Spring-osgi/Spring Framework Web Application Part 3 - 找到我的Bean

    來自八進制的博客

      1. Equinox OSGi服務(wù)器應(yīng)用程序的配置步驟
      2. 利用OSGi DS實現(xiàn)可配置Web應(yīng)用程序初探

    來自羅明的博客

      1. 讓OSGi支持JSF Web開發(fā)
      2. [OSGi]為什么我們需要Bnd?

    來自yangbutao的博客

      1. OSGI 服務(wù)層探究
      2. OSGI Module & lifecycle

    來自erylee的博客

      1. OpenCore: OSGi上部署Hibernate的四種方式
      2. OpenCore:OSGi上部署Apache Common Log
      3. OpenCore:基于OSGi開發(fā)純插件體系結(jié)構(gòu)的WEB應(yīng)用程序

    來自

      1. Equinox OSGi系列之一 Equinox入門
      2. Equinox OSGi系列之二 搭建Equinox OSGi核心環(huán)境
      3. Equinox OSGi系列之三 Equinox配置參數(shù)詳解
      4. Equinox OSGi系列之四 創(chuàng)建自己的OSGi應(yīng)用項目 

    來自IBM 的developerworks

      1. 利用 Eclipse 開發(fā)基于 OSGi 的 Bundle 應(yīng)用(2006 年 7 月 17 日)
      2. 基于 OSGi 的面向服務(wù)的組件編程(2007 年 8 月 31 日)

    來自其他的博客或帖子:

      1. SOA應(yīng)用系統(tǒng)總體框架及相關(guān)概念
      2. SCA與OSGi真的具有可比性嗎?【推薦】
      3. Eclipse(3.1) Plugin Framework(基于OSGI的Plugin Architecture)
      4. 談?wù)刼sgi中的事件機制
      5. 基于Web的OSGi框架構(gòu)想
      6. From JavaWorld  "Hello, OSGi, Part 1: Bundles for beginners" "Hello, OSGi, Part 3: Take it to the server side - JavaWorld"

    posted @ 2008-12-11 14:40 追風(fēng)舞者 閱讀(221) | 評論 (0)編輯 收藏

    剛剛找到的面試題目。自己做了一下,反正挺慘不人睹的。貼出來就想幫幫有需要的人
    并且問問為什么是這個結(jié)果呢?有的題的答案真的想不到啊~想不到~

    一、判斷題(30分)
    1.Java程序里,創(chuàng)建新的類對象用關(guān)鍵字new,回收無用的類對象使用關(guān)鍵字free。
    2.對象可以賦值,只要使用賦值號(等號)即可,相當(dāng)于生成了一個各屬性與賦值對象相同的新對象。
    3.有的類定義時可以不定義構(gòu)造函數(shù),所以構(gòu)造函數(shù)不是必需的。
    4.類及其屬性、方法可以同時有一個以上的修飾符來修飾。
    5.Java的屏幕坐標(biāo)是以像素為單位,容器的左下角被確定為坐標(biāo)的起點
    6.抽象方法必須在抽象類中,所以抽象類中的方法都必須是抽象方法。
    7.Final類中的屬性和方法都必須被final修飾符修飾。
    8.最終類不能派生子類,最終方法不能被覆蓋。
    9.子類要調(diào)用父類的方法,必須使用super關(guān)鍵字。
    10.一個Java類可以有多個父類。
    11.如果p是父類Parent的對象,而c是子類Child的對象,則語句c = p是正確的。
    12.在java集合中,Vector和HashMap是線程安全的。
    13.當(dāng)一個方法在運行過程中產(chǎn)生一個異常,則這個方法會終止,但是整個程序不一定終止運行。
    14.接口是特殊的類,所以接口也可以繼承,子接口將繼承父接口的所有常量和抽象方法。
    15.用“+”可以實現(xiàn)字符串的拼接,用- 可以從一個字符串中去除一個字符子串。

    二、選擇題(30分)
    1、關(guān)于垃圾收集的哪些敘述是正確的(   ):
    A.程序開發(fā)者必須自己創(chuàng)建一個線程進行內(nèi)存釋放的工作
    B.垃圾收集允許程序開發(fā)者明確指定并立即釋放該內(nèi)存
    C.垃圾收集將檢查并釋放不再使用的內(nèi)存
    D.垃圾收集能夠在期望的時間釋放被java對象使用的內(nèi)存
    2、下面的哪些賦值語句是不正確的(   ):
    A.float f=11.1;
    B.double d=5.3E12;
    C.double d=3.14159;
    D.double d=3.14D;
    3、下面關(guān)于變量及其范圍的陳述哪些是不正確的(   ):
    A.實例變量是類的成員變量
    B.實例變量用關(guān)鍵字static聲明
    C.在方法中定義的局部變量在該方法被執(zhí)行時創(chuàng)建
    D.局部變量在使用前必須被初始化
    4、下列關(guān)于修飾符混用的說法,錯誤的是(  ):
    A.a(chǎn)bstract不能與final并列修飾同一個類
    B.a(chǎn)bstract類中不可以有private的成員
    C.a(chǎn)bstract方法必須在abstract類中
    D.static方法中能處理非static的屬性
    5、容器Panel和Applet缺省使用的布局編輯策略是(    ):
    A、BorderLayout  B、FlowLayout      C、GridLayout      D、CardLayout
    6、以下標(biāo)識符中哪項是不合法的(    ):
    A、 BigMeaninglessName                     B、$int
    C、1 st                                    D、$1
    7、main方法是Java  Application程序執(zhí)行的入口點,關(guān)于main方法的方法頭以下哪項是合法的(    ):
    A、    public  static  void  main()   
    B、    public  static  void   main(String[ ]  args)
    C、    public  static int  main(String[ ]  arg)
    D、    public  void  main(String  arg[ ])
    8、執(zhí)行完以下代碼int [ ]  x = new  int[25];后,以下哪項說明是正確的(    ):
    A、    x[24]為0
    B、    x[24]未定義
    C、    x[25]為0
    D、    x[0]為空
    9、以下代碼段執(zhí)行后的輸出結(jié)果為(     ):
           int  x=3; int  y=10;
           System.out.println(y%x);
    A、0
    B、1
    C、2
    D、3
    10、以下哪個表達式是不合法的(    ):
    A、String  x=”Hello”;   int  y=9;   x+=y;
    B、String  x=”Hello”;   int  y=9;  if(x= =y)  { }
    C、String  x=”Hello”;  int  y=9;  x=x+y;
    D、String  x=null;  int  y=(x!=null)&&(x.length()>0) ? x.length : 0
    11、編譯運行以下程序后,關(guān)于輸出結(jié)果的說明正確的是 (    ):
           public  class   Conditional{
                  public  static  void  main(String  args[  ]){
                         int  x=4;
                         System.out.println(“value  is  “+ ((x>4) ? 99.9 :9));
    }
    }
    A、    輸出結(jié)果為:value  is  99.99
    B、    輸出結(jié)果為:value  is  9
    C、    輸出結(jié)果為:value  is  9.0
    D、    編譯錯誤
    12、以下聲明合法的是(     ):
    A、    default  String  s;
    B、    public  final  static  native  int  w( )
    C、    abstract  double  d;
    D、    abstract  final  double  hyperbolicCosine( )
    13、關(guān)于以下application的說明,正確的是(    ):
    1.  class   StaticStuff
    2. {
    3.                  static  int  x=10;
    4.                  static  { x+=5;}
    5.                  public  static  void  main(String  args[ ])
    6.                  {
    7.                       System.out.println(“x=” + x);
    8.                  }
    9.                  static  { x/=3;}
    10.   }
    A、 4行與9行不能通過編譯,因為缺少方法名和返回類型 
    B、 9行不能通過編譯,因為只能有一個靜態(tài)初始化器
    C、 編譯通過,執(zhí)行結(jié)果為:x=5
    D、編譯通過,執(zhí)行結(jié)果為:x=3
    14、關(guān)于以下程序代碼的說明正確的是(   ):
    1.class  HasStatic{
    2.    private  static  int  x=100;
    3.    public  static  void  main(String  args[  ]){
    4.        HasStatic  hs1=new  HasStatic(  );
    5.        hs1.x++;
    6.        HasStatic  hs2=new  HasStatic(  );
    7.        hs2.x++;
    8.        hs1=new  HasStatic( );
    9.        hs1.x++;
    10.       HasStatic.x- -;
    11.       System.out.println(“x=”+x);
    12.   }
    13.}
    A、5行不能通過編譯,因為引用了私有靜態(tài)變量
    B、10行不能通過編譯,因為x是私有靜態(tài)變量
    C、程序通過編譯,輸出結(jié)果為:x=103
    D、程序通過編譯,輸出結(jié)果為:x=102
    15、以下選項中循環(huán)結(jié)構(gòu)合法的是(    ):
    A、while (int  i<7){
         i++;
         System.out.println(“i is “+i);
    }
    B、int  j=3;
    while(j){
       System.out.println(“ j  is “+j);
    }
    C、int  j=0;
    for(int  k=0; j + k !=10; j++,k++){
        System.out.println(“ j  is “+ j + “k  is”+ k);
    }
    D、int  j=0;
    do{
            System.out.println( “j  is “+j++);
            if (j = = 3) {continue  loop;}
    }while  (j<10);

    三、簡答題(40分)
    1.    寫出下列程序的運行結(jié)果
    public class Cat
    {  
      void mi( ) throws NullPointerException
      {
        System.out.println( “Cat mi mi .. “ );
      }
    }
    public class SmallCat extends Cat
    {int i=8;
      void mi( ) throws Exception
      {
        System.out.println( “SmallCat mi mi .. “ );
      }
      public static void main( String[] a ) throws Exception
      {
        Cat cat = new SmallCat();
        cat.mi();
      }
    }


    寫出下列程序的運行結(jié)果
    interface Playable {
        void play();
    }
    interface Bounceable {
        void play();
    }
    interface Rollable extends Playable, Bounceable {
        Ball ball = new Ball("PingPang");
    }
    class Ball implements Rollable {
        private String name;
        public String getName() {
            return name;
        }
        public Ball(String name) {
            this.name = name;       
        }
       public void play() {
            ball = new Ball("Football");
            System.out.println(ball.getName());
        }
    }

    寫出下列程序的運行結(jié)果
    class Value{
    public int i = 15;
    }
    public class Test{
    public static void main(String argv[]){
           Test t = new Test();
        t.first();
       }
    public void first(){
           int i = 5;
           Value v = new Value();
          v.i = 25;
          second(v, i);
          System.out.println(v.i);
       }
    public void second(Value v, int i){
          i = 0;
           v.i = 20;
         Value val = new Value();
            v = val;
            System.out.println(v.i + " " + i);
          }
    }


    寫出下列程序的運行結(jié)果
    class MyThread extends Thread{
    public void run(){
    System.out.println("MyThread: run()");
    }
    public void start(){
    System.out.println("MyThread: start()");
        }
    }
    class MyRunnable implements Runnable{
    public void run(){
    System.out.println("MyRunnable: run()");
        }
    public void start(){
    System.out.println("MyRunnable: start()");
       }
    }
    public class MyTest {
    public static void main(String args[]){
    MyThread myThread  =  new MyThread();
    MyRunnable myRunnable = new MyRunnable();
    Thread thread  =  new Thread(myRunnable);
    myThread.start();
    thread.start();
    }
    }

    posted @ 2008-12-03 09:57 追風(fēng)舞者 閱讀(396) | 評論 (0)編輯 收藏

    一、參考資料:

    1. Tuning Garbage Collection with the 5.0 Java Virtual Machine 官方指南。
    2. Hotspot memory management whitepaper 官方白皮書。
    3. Java Tuning White Paper 官方文檔。
    4. FAQ about Garbage Collection in the Hotspot  官方FAQ,JVM1.4.2。
    5. Java HotSpot 虛擬機中的垃圾收集 JavaOne2004上的中文ppt
    6. A Collection of JVM Options JVM選項的超完整收集。

    二、基本概念

    1、堆(Heap)

    JVM管理的內(nèi)存叫堆。在32Bit操作系統(tǒng)上有1.5G-2G的限制,而64Bit的就沒有。

    JVM初始分配的內(nèi)存由-Xms指定,默認(rèn)是物理內(nèi)存的1/64但小于1G。

    JVM最大分配的內(nèi)存由-Xmx指定,默認(rèn)是物理內(nèi)存的1/4但小于1G。

    默認(rèn)空余堆內(nèi)存小于40%時,JVM就會增大堆直到-Xmx的最大限制,可以由-XX:MinHeapFreeRatio=指定。
    默認(rèn)空余堆內(nèi)存大于70%時,JVM會減少堆直到-Xms的最小限制,可以由-XX:MaxHeapFreeRatio=指定。

    服務(wù)器一般設(shè)置-Xms、-Xmx相等以避免在每次GC 后調(diào)整堆的大小,所以上面的兩個參數(shù)沒啥用。 

    2.基本收集算法

    1. 復(fù)制:將堆內(nèi)分成兩個相同空間,從根(ThreadLocal的對象,靜態(tài)對象)開始訪問每一個關(guān)聯(lián)的活躍對象,將空間A的活躍對象全部復(fù)制到空間B,然后一次性回收整個空間A。
      因為只訪問活躍對象,將所有活動對象復(fù)制走之后就清空整個空間,不用去訪問死對象,所以遍歷空間的成本較小,但需要巨大的復(fù)制成本和較多的內(nèi)存。
    2. 標(biāo)記清除(mark-sweep):收集器先從根開始訪問所有活躍對象,標(biāo)記為活躍對象。然后再遍歷一次整個內(nèi)存區(qū)域,把所有沒有標(biāo)記活躍的對象進行回收處理。該算法遍歷整個空間的成本較大暫停時間隨空間大小線性增大,而且整理后堆里的碎片很多。
    3. 標(biāo)記整理(mark-sweep-compact):綜合了上述兩者的做法和優(yōu)點,先標(biāo)記活躍對象,然后將其合并成較大的內(nèi)存塊。

        可見,沒有免費的午餐,無論采用復(fù)制還是標(biāo)記清除算法,自動的東西都要付出很大的性能代價。

    3.分代

        分代是Java垃圾收集的一大亮點,根據(jù)對象的生命周期長短,把堆分為3個代:Young,Old和Permanent,根據(jù)不同代的特點采用不同的收集算法,揚長避短也。

    Young(Nursery),年輕代。研究表明大部分對象都是朝生暮死,隨生隨滅的。因此所有收集器都為年輕代選擇了復(fù)制算法。
        復(fù)制算法優(yōu)點是只訪問活躍對象,缺點是復(fù)制成本高。因為年輕代只有少量的對象能熬到垃圾收集,因此只需少量的復(fù)制成本。而且復(fù)制收集器只訪問活躍對象,對那些占了最大比率的死對象視而不見,充分發(fā)揮了它遍歷空間成本低的優(yōu)點。

        Young的默認(rèn)值為4M,隨堆內(nèi)存增大,約為1/15,JVM會根據(jù)情況動態(tài)管理其大小變化。
        -XX:NewRatio= 參數(shù)可以設(shè)置Young與Old的大小比例,-server時默認(rèn)為1:2,但實際上young啟動時遠低于這個比率?如果信不過JVM,也可以用-Xmn硬性規(guī)定其大小,有文檔推薦設(shè)為Heap總大小的1/4。

        Young的大小非常非常重要,見“后面暫停時間優(yōu)先收集器”的論述。

        Young里面又分為3個區(qū)域,一個Eden,所有新建對象都會存在于該區(qū),兩個Survivor區(qū),用來實施復(fù)制算法。每次復(fù)制就是將Eden和第一塊Survior的活對象復(fù)制到第2塊,然后清空Eden與第一塊Survior。Eden與Survivor的比例由-XX:SurvivorRatio=設(shè)置,默認(rèn)為32。Survivio大了會浪費,小了的話,會使一些年輕對象潛逃到老人區(qū),引起老人區(qū)的不安,但這個參數(shù)對性能并不重要。 

    Old(Tenured),年老代。年輕代的對象如果能夠挺過數(shù)次收集,就會進入老人區(qū)。老人區(qū)使用標(biāo)記整理算法。因為老人區(qū)的對象都沒那么容易死的,采用復(fù)制算法就要反復(fù)的復(fù)制對象,很不合算,只好采用標(biāo)記清理算法,但標(biāo)記清理算法其實也不輕松,每次都要遍歷區(qū)域內(nèi)所有對象,所以還是沒有免費的午餐啊。

    -XX:MaxTenuringThreshold=設(shè)置熬過年輕代多少次收集后移入老人區(qū),CMS中默認(rèn)為0,熬過第一次GC就轉(zhuǎn)入,可以用-XX:+PrintTenuringDistribution查看。

    Permanent,持久代。裝載Class信息等基礎(chǔ)數(shù)據(jù),默認(rèn)64M,如果是類很多很多的服務(wù)程序,需要加大其設(shè)置-XX:MaxPermSize=,否則它滿了之后會引起fullgc()或Out of Memory。 注意Spring,Hibernate這類喜歡AOP動態(tài)生成類的框架需要更多的持久代內(nèi)存。

    4.minor/major collection

        每個代滿了之后都會促發(fā)collection,(另外Concurrent Low Pause Collector默認(rèn)在老人區(qū)68%的時候促發(fā))。GC用較高的頻率對young進行掃描和回收,這種叫做minor collection
    而因為成本關(guān)系對Old的檢查回收頻率要低很多,同時對Young和Old的收集稱為major collection。
        System.gc()會引發(fā)major collection,使用-XX:+DisableExplicitGC禁止它,或設(shè)為CMS并發(fā)-XX:+ExplicitGCInvokesConcurrent。

    5.小結(jié)

    Young -- minor collection -- 復(fù)制算法

    Old(Tenured) -- major colletion -- 標(biāo)記清除/標(biāo)記整理算法

    三、收集器

    1.古老的串行收集器(Serial Collector)

        使用 -XX:+UseSerialGC,策略為年輕代串行復(fù)制,年老代串行標(biāo)記整理。

    2.吞吐量優(yōu)先的并行收集器(Throughput Collector)

        使用 -XX:+UseParallelGC ,也是JDK5 -server的默認(rèn)值。策略為:
        1.年輕代暫停應(yīng)用程序,多個垃圾收集線程并行的復(fù)制收集,線程數(shù)默認(rèn)為CPU個數(shù),CPU很多時,可用–XX:ParallelGCThreads=減少線程數(shù)。
        2.年老代暫停應(yīng)用程序,與串行收集器一樣,單垃圾收集線程標(biāo)記整理。

        所以需要2+的CPU時才會優(yōu)于串行收集器,適用于后臺處理,科學(xué)計算。

        可以使用-XX:MaxGCPauseMillis= 和 -XX:GCTimeRatio 來調(diào)整GC的時間。

    3.暫停時間優(yōu)先的并發(fā)收集器(Concurrent Low Pause Collector-CMS)

        前面說了這么多,都是為了這節(jié)做鋪墊......

        使用-XX:+UseConcMarkSweepGC,策略為:
        1.年輕代同樣是暫停應(yīng)用程序,多個垃圾收集線程并行的復(fù)制收集。
        2.年老代則只有兩次短暫停,其他時間應(yīng)用程序與收集線程并發(fā)的清除。

    3.1 年老代詳述

        并行(Parallel)與并發(fā)(Concurrent)僅一字之差,并行指多條垃圾收集線程并行,并發(fā)指用戶線程與垃圾收集線程并發(fā),程序在繼續(xù)運行,而垃圾收集程序運行于另一個個CPU上。

        并發(fā)收集一開始會很短暫的停止一次所有線程來開始初始標(biāo)記根對象,然后標(biāo)記線程與應(yīng)用線程一起并發(fā)運行,最后又很短的暫停一次,多線程并行的重新標(biāo)記之前可能因為并發(fā)而漏掉的對象,然后就開始與應(yīng)用程序并發(fā)的清除過程。可見,最長的兩個遍歷過程都是與應(yīng)用程序并發(fā)執(zhí)行的,比以前的串行算法改進太多太多了!!!

        串行標(biāo)記清除是等年老代滿了再開始收集的,而并發(fā)收集因為要與應(yīng)用程序一起運行,如果滿了才收集,應(yīng)用程序就無內(nèi)存可用,所以系統(tǒng)默認(rèn)68%滿的時候就開始收集。內(nèi)存已設(shè)得較大,吃內(nèi)存又沒有這么快的時候,可以用-XX:CMSInitiatingOccupancyFraction=恰當(dāng)增大該比率。

    3.2 年輕代詳述

       可惜對年輕代的復(fù)制收集,依然必須停止所有應(yīng)用程序線程,原理如此,只能靠多CPU,多收集線程并發(fā)來提高收集速度,但除非你的Server獨占整臺服務(wù)器,否則如果服務(wù)器上本身還有很多其他線程時,切換起來速度就..... 所以,搞到最后,暫停時間的瓶頸就落在了年輕代的復(fù)制算法上。

        因此Young的大小設(shè)置挺重要的,大點就不用頻繁GC,而且增大GC的間隔后,可以讓多點對象自己死掉而不用復(fù)制了。但Young增大時,GC造成的停頓時間攀升得非常恐怖,比如在我的機器上,默認(rèn)8M的Young,只需要幾毫秒的時間,64M就升到90毫秒,而升到256M時,就要到300毫秒了,峰值還會攀到恐怖的800ms。誰叫復(fù)制算法,要等Young滿了才開始收集,開始收集就要停止所有線程呢。

    3.3 持久代

    可設(shè)置-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled,使CMS收集持久代的類,而不是fullgc,netbeans5.5 performance文檔的推薦。

    4.增量(train算法)收集器(Incremental Collector)

    已停止維護,–Xincgc選項默認(rèn)轉(zhuǎn)為并發(fā)收集器。

    四、暫停時間顯示

     加入下列參數(shù) (請將PrintGC和Details中間的空格去掉,CSDN很怪的認(rèn)為是禁止字句) 

    -verbose:gc -XX:+PrintGC Details  -XX:+PrintGCTimeStamps

    會程序運行過程中將顯示如下輸出

     9.211: [GC 9.211: [ParNew: 7994K->0K(8128K), 0.0123935 secs] 427172K->419977K(524224K), 0.0125728 secs]

     顯示在程序運行的9.211秒發(fā)生了Minor的垃圾收集,前一段數(shù)據(jù)針對新生區(qū),從7994k整理為0k,新生區(qū)總大小為8128k,程序暫停了12ms,而后一段數(shù)據(jù)針對整個堆。

    對于年老代的收集,暫停發(fā)生在下面兩個階段,CMS-remark的中斷是17毫秒:

    [GC [1 CMS-initial-mark: 80168K(196608K)] 81144K(261184K), 0.0059036 secs] 

    [1 CMS-remark: 80168K(196608K)] 82493K(261184K),0.0168943 secs]

    再加兩個參數(shù) -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime對暫停時間看得更清晰。

    五、真正不停的BEA JRockit 與Sun RTS2.0

       Bea的JRockit 5.0 R27 的特色之一是動態(tài)決定的垃圾收集策略,用戶可以決定自己關(guān)心的是吞吐量,暫停時間還是確定的暫停時間,再由JVM在運行時動態(tài)決定、改變改變垃圾收集策略。
       
       它的Deterministic GC的選項是-Xgcprio: deterministic,號稱可以把暫停可以控制在10-30毫秒,非常的牛,一句Deterministic道盡了RealTime的真諦。 不過細看一下文檔,30ms的測試環(huán)境是1 GB heap 和 平均  30% 的活躍對象(也就是300M)活動對象,2 個 Xeon 3.6 GHz  4G內(nèi)存 ,或者是4 個Xeon 2.0 GHz,8G內(nèi)存。

      最可惜JRockt的license很奇怪,雖然平時使用免費,但這個30ms的選項就需要購買整個Weblogic Real Time Server的license。 

      其他免費選項,有:

    • -Xgcprio:pausetime -Xpausetarget=210ms 
        因為免費,所以最低只能設(shè)置到200ms pause target。 200ms是Sun認(rèn)為Real-Time的分界線。
    • -Xgc:gencon
      普通的并發(fā)做法,效率也不錯。

      JavaOne2007上有Sun的 Java Real-Time System 2.0 的介紹,RTS2.0基于JDK1.5,在Real-Time  Garbage Collctor上又有改進,但還在beta版狀態(tài),只供給OEM,更怪。

    六、JDK 6.0的改進

    因為JDK5.0在Young較大時的表現(xiàn)還是不夠讓人滿意,又繼續(xù)看JDK6.0的改進,結(jié)果稍稍失望,不涉及我最頭痛的年輕代復(fù)制收集改良。

    1.年老代的標(biāo)識-清除收集,并行執(zhí)行標(biāo)識
      JDK5.0只開了一條收集進程與應(yīng)用線程并發(fā)標(biāo)識,而6.0可以開多條收集線程來做標(biāo)識,縮短標(biāo)識老人區(qū)所有活動對象的時間。

    2.加大了Young區(qū)的默認(rèn)大小
    默認(rèn)大小從4M加到16M,從堆內(nèi)存的1/15增加到1/7

    3.System.gc()可以與應(yīng)用程序并發(fā)執(zhí)行
    使用-XX:+ExplicitGCInvokesConcurrent 設(shè)置

    七、小結(jié)

    1. JDK5.0/6.0

    對于服務(wù)器應(yīng)用,我們使用Concurrent Low Pause Collector,對年輕代,暫停時多線程并行復(fù)制收集;對年老代,收集器與應(yīng)用程序并行標(biāo)記--整理收集,以達到盡量短的垃圾收集時間。

    本著沒有深刻測試前不要胡亂優(yōu)化的宗旨,命令行屬性只需簡單寫為:

    -server -Xms<heapsize>M -Xmx<heapsize>M -XX:+UseConcMarkSweepGC  -XX:+PrintGC Details  -XX:+PrintGCTimeStamps

    然后要根據(jù)應(yīng)用的情況,在測試軟件輔助可以下看看有沒有JVM的默認(rèn)值和自動管理做的不夠的地方可以調(diào)整,如-xmn 設(shè)Young的大小,-XX:MaxPermSize設(shè)持久代大小等。

    2. JRockit 6.0 R27.2

    但因為JDK5的測試結(jié)果實在不能滿意,后來又嘗試了JRockit,總體效果要好些。
     JRockit的特點是動態(tài)垃圾收集器是根據(jù)用戶關(guān)心的特征動態(tài)決定收集算法的,參數(shù)如下

     -Xms<heapsize>M -Xmx<heapsize>M -Xgcprio:pausetime -Xpausetarget=200ms -XgcReport -XgcPause -Xverbose:memory

    posted @ 2008-12-03 09:51 追風(fēng)舞者 閱讀(218) | 評論 (0)編輯 收藏

    1.垃圾收集算法的核心思想

      Java語言建立了垃圾收集機制,用以跟蹤正在使用的對象和發(fā)現(xiàn)并回收不再使用(引用)的對象。該機制可以有效防范動態(tài)內(nèi)存分配中可能發(fā)生的兩個危險:因內(nèi)存垃圾過多而引發(fā)的內(nèi)存耗盡,以及不恰當(dāng)?shù)膬?nèi)存釋放所造成的內(nèi)存非法引用。

      垃圾收集算法的核心思想是:對虛擬機可用內(nèi)存空間,即堆空間中的對象進行識別,如果對象正在被引用,那么稱其為存活對象,反之,如果對象不再被引用,則為垃圾對象,可以回收其占據(jù)的空間,用于再分配。垃圾收集算法的選擇和垃圾收集系統(tǒng)參數(shù)的合理調(diào)節(jié)直接影響著系統(tǒng)性能,因此需要開發(fā)人員做比較深入的了解。

    2.觸發(fā)主GC(Garbage Collector)的條件

      JVM進行次GC的頻率很高,但因為這種GC占用時間極短,所以對系統(tǒng)產(chǎn)生的影響不大。更值得關(guān)注的是主GC的觸發(fā)條件,因為它對系統(tǒng)影響很明顯。總的來說,有兩個條件會觸發(fā)主GC:
     

      ①當(dāng)應(yīng)用程序空閑時,即沒有應(yīng)用線程在運行時,GC會被調(diào)用。因為GC在優(yōu)先級最低的線程中進行,所以當(dāng)應(yīng)用忙時,GC線程就不會被調(diào)用,但以下條件除外。

      ②Java堆內(nèi)存不足時,GC會被調(diào)用。當(dāng)應(yīng)用線程在運行,并在運行過程中創(chuàng)建新對象,若這時內(nèi)存空間不足,JVM就會強制地調(diào)用GC線程,以便回收內(nèi)存用于新的分配。若GC一次之后仍不能滿足內(nèi)存分配的要求,JVM會再進行兩次GC作進一步的嘗試,若仍無法滿足要求,則 JVM將報“out of memory”的錯誤,Java應(yīng)用將停止。

      由于是否進行主GC由JVM根據(jù)系統(tǒng)環(huán)境決定,而系統(tǒng)環(huán)境在不斷的變化當(dāng)中,所以主GC的運行具有不確定性,無法預(yù)計它何時必然出現(xiàn),但可以確定的是對一個長期運行的應(yīng)用來說,其主GC是反復(fù)進行的。

    3.減少GC開銷的措施

      根據(jù)上述GC的機制,程序的運行會直接影響系統(tǒng)環(huán)境的變化,從而影響GC的觸發(fā)。若不針對GC的特點進行設(shè)計和編碼,就會出現(xiàn)內(nèi)存駐留等一系列負面影響。為了避免這些影響,基本的原則就是盡可能地減少垃圾和減少GC過程中的開銷。具體措施包括以下幾個方面:

      (1)不要顯式調(diào)用System.gc()

      此函數(shù)建議JVM進行主GC,雖然只是建議而非一定,但很多情況下它會觸發(fā)主GC,從而增加主GC的頻率,也即增加了間歇性停頓的次數(shù)。

      (2)盡量減少臨時對象的使用

      臨時對象在跳出函數(shù)調(diào)用后,會成為垃圾,少用臨時變量就相當(dāng)于減少了垃圾的產(chǎn)生,從而延長了出現(xiàn)上述第二個觸發(fā)條件出現(xiàn)的時間,減少了主GC的機會。

      (3)對象不用時最好顯式置為Null

      一般而言,為Null的對象都會被作為垃圾處理,所以將不用的對象顯式地設(shè)為Null,有利于GC收集器判定垃圾,從而提高了GC的效率。

      (4)盡量使用StringBuffer,而不用String來累加字符串(詳見blog另一篇文章JAVA中String與StringBuffer)

      由于String是固定長的字符串對象,累加String對象時,并非在一個String對象中擴增,而是重新創(chuàng)建新的String對象,如Str5=Str1+Str2+Str3+Str4,這條語句執(zhí)行過程中會產(chǎn)生多個垃圾對象,因為對次作“+”操作時都必須創(chuàng)建新的String對象,但這些過渡對象對系統(tǒng)來說是沒有實際意義的,只會增加更多的垃圾。避免這種情況可以改用StringBuffer來累加字符串,因StringBuffer是可變長的,它在原有基礎(chǔ)上進行擴增,不會產(chǎn)生中間對象。

      (5)能用基本類型如Int,Long,就不用Integer,Long對象

      基本類型變量占用的內(nèi)存資源比相應(yīng)對象占用的少得多,如果沒有必要,最好使用基本變量。

      (6)盡量少用靜態(tài)對象變量

      靜態(tài)變量屬于全局變量,不會被GC回收,它們會一直占用內(nèi)存。

      (7)分散對象創(chuàng)建或刪除的時間

      集中在短時間內(nèi)大量創(chuàng)建新對象,特別是大對象,會導(dǎo)致突然需要大量內(nèi)存,JVM在面臨這種情況時,只能進行主GC,以回收內(nèi)存或整合內(nèi)存碎片,從而增加主GC的頻率。集中刪除對象,道理也是一樣的。它使得突然出現(xiàn)了大量的垃圾對象,空閑空間必然減少,從而大大增加了下一次創(chuàng)建新對象時強制主GC的機會。

    4.gc與finalize方法

      ⑴gc方法請求垃圾回收

      使用System.gc()可以不管JVM使用的是哪一種垃圾回收的算法,都可以請求Java的垃圾回收。需要注意的是,調(diào)用System.gc()也僅僅是一個請求。JVM接受這個消息后,并不是立即做垃圾回收,而只是對幾個垃圾回收算法做了加權(quán),使垃圾回收操作容易發(fā)生,或提早發(fā)生,或回收較多而已。

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

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

      protected void finalize() throws Throwable

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

      因此,當(dāng)對象即將被銷毀時,有時需要做一些善后工作。可以把這些操作寫在finalize()方法里。

     

    java 代碼
    1. protected void finalize()    
    2.    {    
    3.    // finalization code here    
    4.    }  

     

    ⑶代碼示例

    java 代碼
    1. class Garbage{    
    2.    int index;    
    3.    static int count;    
    4.   
    5.    Garbage() {    
    6.    count++;    
    7.    System.out.println("object "+count+" construct");    
    8.    setID(count);    
    9.    }    
    10.   
    11.    void setID(int id) {    
    12.    index=id;    
    13.    }    
    14.   
    15.    protected void finalize() //重寫finalize方法    
    16.    {    
    17.    System.out.println("object "+index+" is reclaimed");    
    18.    }    
    19.   
    20.    public static void main(String[] args)    
    21.    {    
    22.    new Garbage();    
    23.    new Garbage();    
    24.    new Garbage();    
    25.    new Garbage();    
    26.    System.gc(); //請求運行垃圾收集器    
    27.    }    
    28.   
    29.  }  

    5.Java 內(nèi)存泄漏
      由于采用了垃圾回收機制,任何不可達對象(對象不再被引用)都可以由垃圾收集線程回收。因此通常說的Java 內(nèi)存泄漏其實是指無意識的、非故意的對象引用,或者無意識的對象保持。無意識的對象引用是指代碼的開發(fā)人員本來已經(jīng)對對象使用完畢,卻因為編碼的錯誤而意外地保存了對該對象的引用(這個引用的存在并不是編碼人員的主觀意愿),從而使得該對象一直無法被垃圾回收器回收掉,這種本來以為可以釋放掉的卻最終未能被釋放的空間可以認(rèn)為是被“泄漏了”。

      考慮下面的程序,在ObjStack類中,使用push和pop方法來管理堆棧中的對象。兩個方法中的索引(index)用于指示堆棧中下一個可用位置。push方法存儲對新對象的引用并增加索引值,而pop方法減小索引值并返回堆棧最上面的元素。在main方法中,創(chuàng)建了容量為64的棧,并64次調(diào)用push方法向它添加對象,此時index的值為64,隨后又32次調(diào)用pop方法,則index的值變?yōu)?2,出棧意味著在堆棧中的空間應(yīng)該被收集。但事實上,pop方法只是減小了索引值,堆棧仍然保持著對那些對象的引用。故32個無用對象不會被GC回收,造成了內(nèi)存滲漏。

     

    java 代碼
    public class ObjStack {    
    1.    private Object[] stack;    
    2.    private int index;    
    3.    ObjStack(int indexcount) {    
    4.    stack = new Object[indexcount];    
    5.    index = 0;    
    6.    }    
    7.    public void push(Object obj) {    
    8.    stack[index] = obj;    
    9.    index++;    
    10.    }    
    11.    public Object pop() {    
    12.    index--;    
    13.    return stack[index];    
    14.    }    
    15.    }    
    16.    public class Pushpop {    
    17.    public static void main(String[] args) {    
    18.    int i = 0;    
    19.    Object tempobj;    
    20.   
    21. //new一個ObjStack對象,并調(diào)用有參構(gòu)造函數(shù)。分配stack Obj數(shù)組的空間大小為64,可以存64個對象,從0開始存儲   
    22.    ObjStack stack1 = new ObjStack(64);   
    23.   
    24.    while (i < 64)    
    25.    {    
    26.    tempobj = new Object();//循環(huán)new Obj對象,把每次循環(huán)的對象一一存放在stack Obj數(shù)組中。    
    27.    stack1.push(tempobj);    
    28.    i++;    
    29.    System.out.println("第" + i + "次進棧" + "\t");    
    30.    }    
    31.   
    32.    while (i > 32)    
    33.    {    
    34.    tempobj = stack1.pop();//這里造成了空間的浪費。    
    35.    //正確的pop方法可改成如下所指示,當(dāng)引用被返回后,堆棧刪除對他們的引用,因此垃圾收集器在以后可以回收他們。    
    36.    /*   
    37.    * public Object pop() {index - -;Object temp = stack [index];stack [index]=null;return temp;}   
    38.    */    
    39.    i--;    
    40.    System.out.println("第" + (64 - i) + "次出棧" + "\t");    
    41.    }    
    42.    }    
    43.    }  

     

    6.如何消除內(nèi)存泄漏

      雖然Java虛擬機(JVM)及其垃圾收集器(garbage collector,GC)負責(zé)管理大多數(shù)的內(nèi)存任務(wù),Java軟件程序中還是有可能出現(xiàn)內(nèi)存泄漏。實際上,這在大型項目中是一個常見的問題。避免內(nèi)存泄漏的第一步是要弄清楚它是如何發(fā)生的。本文介紹了編寫Java代碼的一些常見的內(nèi)存泄漏陷阱,以及編寫不泄漏代碼的一些最佳實踐。一旦發(fā)生了內(nèi)存泄漏,要指出造成泄漏的代碼是非常困難的。因此本文還介紹了一種新工具,用來診斷泄漏并指出根本原因。該工具的開銷非常小,因此可以使用它來尋找處于生產(chǎn)中的系統(tǒng)的內(nèi)存泄漏。

      垃圾收集器的作用

      雖然垃圾收集器處理了大多數(shù)內(nèi)存管理問題,從而使編程人員的生活變得更輕松了,但是編程人員還是可能犯錯而導(dǎo)致出現(xiàn)內(nèi)存問題。簡單地說,GC循環(huán)地跟蹤所有來自“根”對象(堆棧對象、靜態(tài)對象、JNI句柄指向的對象,諸如此類)的引用,并將所有它所能到達的對象標(biāo)記為活動的。程序只可以操縱這些對象;其他的對象都被刪除了。因為GC使程序不可能到達已被刪除的對象,這么做就是安全的。

      雖然內(nèi)存管理可以說是自動化的,但是這并不能使編程人員免受思考內(nèi)存管理問題之苦。例如,分配(以及釋放)內(nèi)存總會有開銷,雖然這種開銷對編程人員來說是不可見的。創(chuàng)建了太多對象的程序?qū)韧瓿赏瑯拥墓δ芏鴦?chuàng)建的對象卻比較少的程序更慢一些(在其他條件相同的情況下)。

      而且,與本文更為密切相關(guān)的是,如果忘記“釋放”先前分配的內(nèi)存,就可能造成內(nèi)存泄漏。如果程序保留對永遠不再使用的對象的引用,這些對象將會占用并耗盡內(nèi)存,這是因為自動化的垃圾收集器無法證明這些對象將不再使用。正如我們先前所說的,如果存在一個對對象的引用,對象就被定義為活動的,因此不能刪除。為了確保能回收對象占用的內(nèi)存,編程人員必須確保該對象不能到達。這通常是通過將對象字段設(shè)置為null或者從集合(collection)中移除對象而完成的。但是,注意,當(dāng)局部變量不再使用時,沒有必要將其顯式地設(shè)置為null。對這些變量的引用將隨著方法的退出而自動清除。

      概括地說,這就是內(nèi)存托管語言中的內(nèi)存泄漏產(chǎn)生的主要原因:保留下來卻永遠不再使用的對象引用。

      典型泄漏

      既然我們知道了在Java中確實有可能發(fā)生內(nèi)存泄漏,就讓我們來看一些典型的內(nèi)存泄漏及其原因。

      全局集合

      在大的應(yīng)用程序中有某種全局的數(shù)據(jù)儲存庫是很常見的,例如一個JNDI樹或一個會話表。在這些情況下,必須注意管理儲存庫的大小。必須有某種機制從儲存庫中移除不再需要的數(shù)據(jù)。

      這可能有多種方法,但是最常見的一種是周期性運行的某種清除任務(wù)。該任務(wù)將驗證儲存庫中的數(shù)據(jù),并移除任何不再需要的數(shù)據(jù)。

      另一種管理儲存庫的方法是使用反向鏈接(referrer)計數(shù)。然后集合負責(zé)統(tǒng)計集合中每個入口的反向鏈接的數(shù)目。這要求反向鏈接告訴集合何時會退出入口。當(dāng)反向鏈接數(shù)目為零時,該元素就可以從集合中移除了。

      緩存

      緩存是一種數(shù)據(jù)結(jié)構(gòu),用于快速查找已經(jīng)執(zhí)行的操作的結(jié)果。因此,如果一個操作執(zhí)行起來很慢,對于常用的輸入數(shù)據(jù),就可以將操作的結(jié)果緩存,并在下次調(diào)用該操作時使用緩存的數(shù)據(jù)。

      緩存通常都是以動態(tài)方式實現(xiàn)的,其中新的結(jié)果是在執(zhí)行時添加到緩存中的。典型的算法是:

      檢查結(jié)果是否在緩存中,如果在,就返回結(jié)果。

      如果結(jié)果不在緩存中,就進行計算。

      將計算出來的結(jié)果添加到緩存中,以便以后對該操作的調(diào)用可以使用。

      該算法的問題(或者說是潛在的內(nèi)存泄漏)出在最后一步。如果調(diào)用該操作時有相當(dāng)多的不同輸入,就將有相當(dāng)多的結(jié)果存儲在緩存中。很明顯這不是正確的方法。

      為了預(yù)防這種具有潛在破壞性的設(shè)計,程序必須確保對于緩存所使用的內(nèi)存容量有一個上限。因此,更好的算法是:

      檢查結(jié)果是否在緩存中,如果在,就返回結(jié)果。

      如果結(jié)果不在緩存中,就進行計算。

      如果緩存所占的空間過大,就移除緩存最久的結(jié)果。

      將計算出來的結(jié)果添加到緩存中,以便以后對該操作的調(diào)用可以使用。

      通過始終移除緩存最久的結(jié)果,我們實際上進行了這樣的假設(shè):在將來,比起緩存最久的數(shù)據(jù),最近輸入的數(shù)據(jù)更有可能用到。這通常是一個不錯的假設(shè)。

      新算法將確保緩存的容量處于預(yù)定義的內(nèi)存范圍之內(nèi)。確切的范圍可能很難計算,因為緩存中的對象在不斷變化,而且它們的引用包羅萬象。為緩存設(shè)置正確的大小是一項非常復(fù)雜的任務(wù),需要將所使用的內(nèi)存容量與檢索數(shù)據(jù)的速度加以平衡。

      解決這個問題的另一種方法是使用java.lang.ref.SoftReference類跟蹤緩存中的對象。這種方法保證這些引用能夠被移除,如果虛擬機的內(nèi)存用盡而需要更多堆的話。

      ClassLoader

      Java ClassLoader結(jié)構(gòu)的使用為內(nèi)存泄漏提供了許多可乘之機。正是該結(jié)構(gòu)本身的復(fù)雜性使ClassLoader在內(nèi)存泄漏方面存在如此多的問題。ClassLoader的特別之處在于它不僅涉及“常規(guī)”的對象引用,還涉及元對象引用,比如:字段、方法和類。這意味著只要有對字段、方法、類或ClassLoader的對象的引用,ClassLoader就會駐留在JVM中。因為ClassLoader本身可以關(guān)聯(lián)許多類及其靜態(tài)字段,所以就有許多內(nèi)存被泄漏了。

      確定泄漏的位置

      通常發(fā)生內(nèi)存泄漏的第一個跡象是:在應(yīng)用程序中出現(xiàn)了OutOfMemoryError。這通常發(fā)生在您最不愿意它發(fā)生的生產(chǎn)環(huán)境中,此時幾乎不能進行調(diào)試。有可能是因為測試環(huán)境運行應(yīng)用程序的方式與生產(chǎn)系統(tǒng)不完全相同,因而導(dǎo)致泄漏只出現(xiàn)在生產(chǎn)中。在這種情況下,需要使用一些開銷較低的工具來監(jiān)控和查找內(nèi)存泄漏。還需要能夠無需重啟系統(tǒng)或修改代碼就可以將這些工具連接到正在運行的系統(tǒng)上。可能最重要的是,當(dāng)進行分析時,需要能夠斷開工具而保持系統(tǒng)不受干擾。

      雖然OutOfMemoryError通常都是內(nèi)存泄漏的信號,但是也有可能應(yīng)用程序確實正在使用這么多的內(nèi)存;對于后者,或者必須增加JVM可用的堆的數(shù)量,或者對應(yīng)用程序進行某種更改,使它使用較少的內(nèi)存。但是,在許多情況下,OutOfMemoryError都是內(nèi)存泄漏的信號。一種查明方法是不間斷地監(jiān)控GC的活動,確定內(nèi)存使用量是否隨著時間增加。如果確實如此,就可能發(fā)生了內(nèi)存泄漏。

    posted @ 2008-12-03 09:41 追風(fēng)舞者 閱讀(1305) | 評論 (1)編輯 收藏

    主站蜘蛛池模板: 一区二区三区福利视频免费观看| 久久亚洲中文无码咪咪爱| 天黑黑影院在线观看视频高清免费| 国产又黄又爽又刺激的免费网址| 亚洲成_人网站图片| 9久9久女女免费精品视频在线观看| 亚洲欧洲日产v特级毛片| 在线看无码的免费网站| 亚洲精品在线不卡| 无遮免费网站在线入口| 亚洲中文久久精品无码1| 大地资源免费更新在线播放| 亚洲色欲啪啪久久WWW综合网| 四虎成人免费影院网址| 国产亚洲精品AAAA片APP| 免费播放春色aⅴ视频| caoporm超免费公开视频| 亚洲AV无码一区二区二三区入口| 暖暖免费日本在线中文| 亚洲成AV人片久久| 日韩成人在线免费视频| 搜日本一区二区三区免费高清视频 | 亚洲AV无码乱码国产麻豆| 免费看又黄又无码的网站| 亚洲成年人电影网站| 日本成人免费在线| xxxxx做受大片视频免费| 亚洲AV色香蕉一区二区| 永久免费av无码网站韩国毛片| 精品韩国亚洲av无码不卡区 | 久久精品国产亚洲av麻| 午夜国产精品免费观看| 羞羞漫画小舞被黄漫免费| 在线观看午夜亚洲一区| 99在线精品免费视频九九视| 美美女高清毛片视频黄的一免费| 亚洲大片在线观看| 日韩黄色免费观看| 久久免费精彩视频| 亚洲av无码成人精品国产 | 亚洲成人免费在线观看|