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

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

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

    paulwong

    HotSpot 的垃圾收集 - 轉(zhuǎn)

    從J2SE 5.0開始,HotSpot JVM共包含四種垃圾收集器,它們?nèi)炕诜执惴ā?br />一、代的劃分
    HotSpot JVM中內(nèi)存被劃分為三代:年幼代(young generation)、年長代(old generation)和永久代(permanent generation)。從邏輯上講,年幼代和年長代共同構(gòu)成了Java堆,而永久代則被稱為方法區(qū)(method area)。除了一些大對象可能在年長區(qū)中直接分配外,大部分對象都在年幼區(qū)中創(chuàng)建;而年長區(qū)除了那些直接創(chuàng)建的大對象外,大部分對象都是在年幼區(qū)中歷經(jīng)幾次垃圾收集而幸免于難后被提升過來的。永久代中則保存著已載入類型的相關(guān)信息,包含了類、方法和其他一些內(nèi)部使用的元數(shù)據(jù),所有這些信息同樣以對象的形式來組織和表示,雖然這些對象并不是Java對象,但是它們卻象Java對象一樣可以被同樣的垃圾收集器所收集;另外,java.lang.String類所管理的內(nèi)在化的字符串緩存池也在該代中分配;雖然名字叫做“永久”代,但其中的對象并不是永久的,只是沿用了歷史名稱而已。
    年幼代由一個伊甸區(qū)(Eden Space)和兩個更小的生還區(qū)(Survivor Space)組成,如下圖所示(該圖為縮略圖,請點擊察看原圖)。大部分對象在伊甸區(qū)中創(chuàng)建,少數(shù)大對象可能在年長代中直接創(chuàng)建。生還區(qū)中保存的對象是歷經(jīng)一次或多次對年幼代的垃圾收集而未死的幸存者,并且在被認為已足夠成熟而提升到年長代之前,它們?nèi)杂性谏院蟮哪炒卫占^程中犧牲的可能。除非處在垃圾收集過程當中,兩個生還區(qū)中只有一個用來容納這些幸存者,另一個則保持為空。
    JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s5.sinaimg.cn/bmiddle/51501580g8169fb66ab44&690">

    二、垃圾收集類型
    年幼代填滿后,一次只針對該代的收集被執(zhí)行,這樣的收集也被稱作“次收集(minor collection)”。當年長代或永久代被填滿后,一次針對所有代的完整收集被執(zhí)行,這樣的收集也被稱作“主收集(major collection)”。通常來說,在一次主收集過程中,年幼代首先被收集,收集算法采用當前收集器的年幼代收集算法,該算法往往是針對年幼對象的行為特征而專門設(shè)計的;然后是對年長代和永久代的收集,收集算法都采用當前收集器的年長代收集算法。對于給定收集器所具體使用的年幼代和年長代收集算法,請參考下文。另外,主收集過程中如果存在壓縮,則每代獨自進行。
    不過,首先收集年幼代的策略在年長代空閑空間太小時會失效,因為年長代已無足夠的空間來接納所有的可能從年幼代提升過來的對象;在這種情況下,除CMS外的所有收集器都會放棄原有的年幼代收集算法,轉(zhuǎn)而統(tǒng)一采用年長代收集算法對所有代進行收集。(CMS收集器之所以例外是因為它的年長代算法不能用來收集年幼代。)

    三、快速分配
    從下文對垃圾收集器的描述中可以看出,在許多情況下,內(nèi)存中都有大塊的連續(xù)空閑空間用以滿足對象的分配請求。這種情形下的分配操作使用簡單的“bump-the-pointer”技術(shù),效率很高。按照這種技術(shù),JVM內(nèi)部維護一個指針(allocatedTail),它始終指向先前已分配對象的尾部,當新的對象分配請求到來時,只需檢查代中剩余空間(從allocatedTail到代尾geneTail)是否足以容納該對象,并在“是”的情況下更新allocatedTail指針并初始化對象。下面的偽代碼具體展示了從連續(xù)內(nèi)存塊中分配對象時分配操作的簡潔性和高效性:
    void * malloc(int n){
    if( geneTail - allocatedTail < n )
    doGarbageCollection();
    void * wasAllocatedTail = allocatedTail;
    allocatedTail += n;
    return wasAllocatedTail;
    }
    對于多線程應(yīng)用,分配操作必須是線程安全的。如果使用全局鎖為此提供保證,則分配操作必定成為一個性能瓶頸。基于此,HotSport JVM采用了一種被稱為“線程局部分配緩沖區(qū)”(Thread-Local Allocation Buffers,TLAB)的技術(shù)。該項技術(shù)為每個線程提供一個獨立的分配緩沖區(qū)(伊甸區(qū)的一小部分),借此來提高分配操作的吞吐量。因為針對每個TLAB,只有一個線程從中分配對象,故而分配操作可以使用“bump-the-pointer”技術(shù)快速完成,而不必使用任何鎖機制;只有當線程將其已有TLAB填滿并且需要獲取一個新的TLAB時,同步才是必須的。同時,為了減少TLAB所帶來的空間消耗,還使用了一些其他技術(shù),例如,分配器能夠把TLAB的平均大小限制在伊甸區(qū)的1%以下。
    “bump-the-pointer”和TLAB技術(shù)的組合保證了分配操作的高效性,類似new Object()這樣的操作在大部分時間內(nèi)只需要大約10條機器指令即可完成。

    四、收集方式
    1)串行(serial)和并行(parallel)
    串行和并行是從收集任務(wù)本身如何被完成的角度來描述收集過程的。采用串行方式收集時,同一時間只有一件事情會發(fā)生。例如,即使有多個CPU可用,還是只有一個被用來執(zhí)行收集任務(wù)。當采用并行方式收集時,垃圾收集任務(wù)被分成許多子任務(wù),并且那些子任務(wù)在不同的CPU上被同時執(zhí)行。同時操作使收集任務(wù)得以更快地完成,代價是增加了任務(wù)的復(fù)雜性并可能產(chǎn)生內(nèi)存碎片。2)STW(stop-the-world)和并發(fā)(concurrent)
    STW和并發(fā)是從收集任務(wù)是否影響應(yīng)用程序執(zhí)行的角度來描述收集過程的。當垃圾收集使用STW方式進行時,在收集期間應(yīng)用程序?qū)⒈煌耆珤炱?。作為另一種選擇,收集任務(wù)可以采取并發(fā)方式,與應(yīng)用程序一起同時執(zhí)行。比較典型的情況是,并發(fā)收集器采取并發(fā)方式完成大部分工作,但也可能偶爾地不得不切換到STW方式,以完成一些需要應(yīng)用程序短暫停頓的工作。STW收集比并發(fā)收集更為簡單,因為在收集期間堆被凍結(jié)、對象不會改變;它的缺點是對某些應(yīng)用程序來說,被暫停過久是不符合要求的。相對地,采用并發(fā)方式進行垃圾收集時,停頓時間會更短,但這也要求收集器必須更加小心,因為它正在操作可能被應(yīng)用程序同時更新的對象。對并發(fā)收集器來說,這會增加額外開銷從而影響性能,也會對堆空間產(chǎn)生更大的需求。

    五、串行收集器(serial collector)
    使用串行收集器時,對年幼代和年長代的收集都采用串行、STW方式進行。也就是說收集任務(wù)同時只使用一個CPU,而且在收集任務(wù)執(zhí)行期間,應(yīng)用程序的執(zhí)行被中止。
    1)串行收集器如何收集年幼代?
    下圖展示了使用串行收集器對年幼代進行收集時的操作細節(jié)。伊甸區(qū)中的活動對象被拷貝到初始為空的生還區(qū)2中;已占用的生還區(qū)1中的活動對象如果仍顯年輕,則同樣被拷貝到生還區(qū)2中,否則被直接拷貝到年長代;需要注意的是,生還區(qū)2一旦被填滿,則所有尚未被拷貝的活動對象,不論其來自伊甸區(qū)還是生還區(qū)1,也不論其曾經(jīng)幸免于多少次次收集,統(tǒng)統(tǒng)被拷貝到年長代。按照定義,在活動對象被拷貝之后,伊甸區(qū)和生還區(qū)1中的對象就全部成為垃圾對象,無須再被檢查。(垃圾對象在圖中以“X”標記,雖然實際上收集器并不檢查和標記這些對象。) JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s4.sinaimg.cn/middle/51501580g81cfe5708d93&690"> 收集完成后,伊甸區(qū)和生還區(qū)1變?yōu)榭臻e空間,活動對象保存在生還區(qū)2中。此時,兩個生還區(qū)的角色已經(jīng)發(fā)生了互換。如下圖:JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s4.sinaimg.cn/middle/51501580g81d362167ce3&690"> 2)串行收集器如何收集年長代?
    串行收集器采用標記-清理-壓縮算法收集年長代和永久代。在標記階段,收集器遍歷引用樹,找出所有活動對象并打上標記;在清理階段,順序掃描代空間中所有對象(不論死活),計算出每個活動對象在代空間中的新位置;在壓縮階段,指向活動對象的所有引用被先期更新后,所有活動對象也被逐個滑動到其新的位置。由于所有活動對象都是按照次序朝代空間頭部移動的,因此就在代空間尾部自然形成了一個單一而連續(xù)的空閑空間。如下圖:JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s3.sinaimg.cn/middle/51501580g81fd1aa883d2&690">壓縮過程使基于年長代或永久代的分配操作可以使用快速的“bump-the-pointer”技術(shù)。
    3)何時使用串行收集器?
    對于運行在客戶端級硬件上并且對停頓時間沒有特別要求的大多數(shù)應(yīng)用而言,串行收集器都是首選。按照目前的硬件水平,串行收集器可以高效地管理使用64MB堆空間、最長停頓時間不能超過半秒的很多重要應(yīng)用。
    4)串行收集器的選用
    在J2SE 5.0版本中,對于非服務(wù)器級硬件而言,串行收集器作為缺省的垃圾收集器被自動選用;對于其他硬件平臺,則可以通過命令行選項“-XX:+UseSerialGC”進行顯示的選用。

    六、并行收集器(parallel collector)
    目前,許多Java應(yīng)用的運行平臺大都包含很多物理內(nèi)存和多個CPU。并行收集器,也被稱作吞吐量收集器,被開發(fā)出來的主要目的就是為了充分利用CPU資源,而不是只讓一個CPU去做垃圾收集而其他CPU卻被閑置。
    1)并行收集器如何收集年幼代?
    和串行收集器相比,并行收集器采用了大致相同的年幼代收集算法,只是執(zhí)行的是其并行版本而已。對年幼代的收集雖然仍基于拷貝技術(shù)、采用STW方式進行,但收集工作是并行展開的,使用了多個CPU,這就降低了垃圾收集開銷,從而提高了應(yīng)用程序的吞吐量。下圖展示了并行收集器和串行收集器在執(zhí)行年幼代收集時到底有何不同:
    JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s7.sinaimg.cn/middle/51501580g81e435e495a6&690">
    2)并行收集器如何收集年長代?
    和串行收集器一樣,并行收集器對年長代的收集同樣基于標記-清理-壓縮算法,同樣采用串行、STW方式進行。
    3)何時使用并行收集器?
    能夠得益于并行收集器的應(yīng)用程序,必定運行在多CPU機器上,并且對停頓時間不能有特別的約束。因為可能持續(xù)時間很長的年長代收集雖然稀少,但還是會發(fā)生的。適于采用并行收集器的典型應(yīng)用包括批處理、記帳、工資單和科學(xué)計算等等。你可能更傾向于選擇并行壓縮收集器(見下文)而不是并行收集器,因為前者對所有代(而不只是年幼代)的收集都采用并行方式進行。
    4)并行收集器的選用
    在J2SE 5.0版本中,對于服務(wù)器級硬件而言,并行收集器作為缺省的垃圾收集器被自動選用;對于其他硬件平臺,則可以通過命令行選項“-XX:+UseParallelGC”進行顯示的選用。

    七、并行壓縮收集器(parallel compacting collector)
    并行壓縮收集器在J2SE 5.0 U6中引入,它和并行收集器的區(qū)別在于,對年長代的收集它使用了全新的算法。注意:并行壓縮收集器終將取代并行收集器。
    1)并行壓縮收集器如何收集年幼代?
    同并行收集器,不再贅述。
    2)并行壓縮收集器如何收集年長代?
    使用并行壓縮收集器時,對年長代和永久代的收集都采用帶滑動壓縮的準并行、STW方式進行。為了滿足并行處理的要求,每一個代空間均被邏輯劃分為諸多定長區(qū)域(fixed-sized region),每個區(qū)域的相關(guān)信息保存在收集器維護的內(nèi)部數(shù)據(jù)結(jié)構(gòu)中。收集過程被分為標記、匯總和壓縮三個階段進行。在標記階段,根引用集被劃分給多個垃圾收集線程,它們同時運行,以并行的方式對活動對象進行追蹤和標記;在活動對象被標記的同時,該對象的起始區(qū)域的數(shù)據(jù)也將被同步更新以反映該活動對象的大小和位置信息。
    在匯總階段(summary phase),操作不再基于對象,而是區(qū)域??紤]到先前收集過程中的壓縮累積效應(yīng),每一個代空間中位于左側(cè)的某一部分通常是密集的,主要包含了活動對象。從這樣的密集區(qū)塊中可能回收的空間數(shù)量使得它們并不值得被壓縮。所以匯總階段的首要任務(wù)就是檢查區(qū)域的密集度,從最左邊一個區(qū)域開始,直到找到這樣的一個區(qū)域,使得在該區(qū)域及其右側(cè)所有區(qū)域中可被回收的空間數(shù)量抵得上對它們進行壓縮的成本。該區(qū)域左側(cè)的所有區(qū)域就被稱為密集前置區(qū)塊,沒有對象會被移入其中。該區(qū)域及其右側(cè)所有區(qū)域會被壓縮,以消除所有死區(qū)。匯總階段的下一個任務(wù)就是計算并保存每個被壓縮區(qū)域中活動數(shù)據(jù)的首字節(jié)在壓縮后的新位置。需要注意的是:匯總階段在目前被實現(xiàn)為一個串行階段,這也是“準”并行方式的由來;并行實現(xiàn)也是可能的,只是與標記和壓縮階段的并行化相比,它對性能的影響不大。
    在壓縮階段,垃圾收集線程使用匯總數(shù)據(jù)確定需要被填充的區(qū)域,然后它們就可以獨立地把對象拷貝到這些區(qū)域中而不再需要額外的同步。這就產(chǎn)生了一個堆,堆空間的一端塞滿了活動對象,而另一端則是一個單一而連續(xù)的空閑內(nèi)存塊。
    3)何時使用并行壓縮收集器?
    和并行收集器一樣,并行壓縮收集器同樣有益于在多CPU機器上運行的應(yīng)用程序。除此之外,年長代收集的并行化操作方式還減少了停頓時間,使得并行壓縮收集器比并行收集器更為適合那些有停頓時間限制的應(yīng)用。不過,對于運行在大型共享主機(如SunRays)上的應(yīng)用來說,并行壓縮收集器也許并不太合適,因為任何單一應(yīng)用都不應(yīng)長時間獨占幾個CPU。在這樣的機器上,要么考慮通過命令行選項“-XX:ParallelGCThreads=n”減少垃圾收集線程的數(shù)目,要么考慮選擇一種不同的收集器。
    4)并行壓縮收集器的選用
    并行壓縮收集器只能通過命令行選項“-XX:+UseParallelOldGC”進行顯示的選用。

    八、并發(fā)的標記-清理收集器(Concurrent Mark-Sweep(CMS) Collector)
    對于許多應(yīng)用來說,端到端的吞吐量并不象響應(yīng)時間那么重要。通常來講,對年幼代的收集并不會引起太長時間的停頓。但是對年長代的收集,雖然不常發(fā)生,卻可能導(dǎo)致停頓時間過長的狀況,在堆空間很大時尤其明顯。為了解決這個問題,HotSpot JVM包含了一個名叫“并發(fā)的標記-清理(CMS)收集器”的收集器,它也被稱為低延遲收集器。
    1)CMS收集器如何收集年幼代?
    同并行收集器,不再贅述。
    2)CMS收集器如何收集年長代?
    采用CMS收集器收集年長代時,大部分收集任務(wù)與應(yīng)用程序并發(fā)執(zhí)行。
    CMS收集器的收集周期始于初始標記,它采用串行、STW方式進行,用于確定根引用集。隨后進入并發(fā)標記階段,完成對所有活動對象的追蹤和標記,在JDK6中該階段已開始采用并行、并發(fā)方式進行。由于在并發(fā)標記過程中應(yīng)用程序正在執(zhí)行并可能更新了一些對象的引用域,因此并發(fā)標記過程結(jié)束時并非所有活動對象都已確保被標記出來。為了處理這種情況,應(yīng)用程序再次暫停,收集過程進入再標記階段;它采用并行、STW方式進行,通過對并發(fā)標記過程中被修改對象的再次訪問最終完成整個標記過程。因為再標記階段的停頓時間往往是最長的(超過初始標記停頓甚至次收集停頓),因此再標記過程會盡量采用并行方式進行。
    再標記階段完成后,所有活動對象都已確保被標記,隨后進入并發(fā)清理階段,它采用串行、并發(fā)方式進行,就地回收所有垃圾對象。下圖展示了串行的標記-清理-壓縮收集器和CMS收集器在收集年長代時的區(qū)別: JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s13.sinaimg.cn/middle/51501580g82676852d74c&690"> 因為一些任務(wù)(例如再標記過程中對被修改對象的再次訪問)增加了收集器的工作量,CMS收集器的總體開銷自然會增大。對于大多數(shù)試圖減少停頓時間的收集器來說,這是一種典型的折衷。
    CMS收集器是唯一一個不使用壓縮技術(shù)的收集器。也就是說,在垃圾對象所占用的空間被釋放以后,收集器并不把活動對象全部推擠到代空間的某一端去。見下圖:JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s3.sinaimg.cn/middle/51501580g82716466bed2&690">這種方式節(jié)省了回收時間,但卻因為空閑空間不再連續(xù),收集器也就不再可能只使用一個簡單指針即可指示出可分配給新對象的下一個空閑空間的位置,相反,它現(xiàn)在需要使用空閑空間列表。也就是說,收集器創(chuàng)建并通過一組列表把內(nèi)存中尚未分配的區(qū)域連接起來,每當有對象需要分配空間時,適當?shù)牧斜恚ɑ谒鑳?nèi)存數(shù)量)被搜索,以找到一塊足以放下該對象的空閑區(qū)域。作為結(jié)果,與使用“bump-the-pointer”技術(shù)時相比,年長代中的分配操作變得更加昂貴。同時這也給年幼代收集帶來了額外的開銷,因為在其收集過程中每提升一個對象都會觸發(fā)一次年長代中的分配操作。
    CMS收集器的另一個缺點是和其他收集器相比它需要更大的堆空間。一方面,由于在標記階段應(yīng)用程序被允許運行,它就可能繼續(xù)分配內(nèi)存,從而可能使年長代空間不斷地增長;另一方面,雖然標記階段完成后所有活動對象都已確保被標記,但是在標記過程中一些對象卻可能變?yōu)槔鴮ο?,而且直到下次年長代收集之前它們不會被回收。這樣的對象也被稱為游浮垃圾。
    CMS收集器的最后一個缺點是由于缺乏壓縮它可能引發(fā)碎片化問題。為了對付碎片化,CMS收集器跟蹤對象的流行尺寸,預(yù)估未來需求,并為滿足需求還可能分割或合并空閑內(nèi)存塊。
    不象其他收集器,CMS收集器并不是等到年長代填滿后才啟動對年長代的收集,而是嘗試盡早啟動年長代收集,以便在年長代被填滿之前收集過程可以完成。否則的話,CMS收集器將重新采用在串行和并行收集器中使用的標記-清理-壓縮算法,盡管該算法工作于STW方式,也更加耗時。為避免這種情況的發(fā)生,CMS收集器對先前收集所耗時間和代空間充滿所耗時間進行統(tǒng)計,并據(jù)此確定收集啟動時間。另外,當年長代的空間占用率超過啟動占用率(initiating occupancy)時,CMS收集器也將啟動一次收集。啟動占用率的值可以通過命令行選項“-XX:CMSInitiatingOccupancyFraction=n”進行設(shè)定,其中 n 表示年長代空間大小的百分比。缺省值為68。
    總的來說,與并行收集器相比,CMS收集器(有時甚至顯著地)減少了年長代收集的停頓時間,而代價是略有增加的年幼代收集的停頓時間、吞吐量方面的一些損失和額外的堆空間需求。
    3)增量模式
    CMS收集器可以采用讓并發(fā)階段增量完成的模式運行。這種模式通過對并發(fā)階段的周期性暫停把處理能力交還給應(yīng)用程序,以減少并發(fā)階段持續(xù)時間過長所帶來的不利影響。收集工作被分成許多小的時間塊,它們在年幼代收集的間歇期被調(diào)度。當應(yīng)用程序既需要CMS收集器提供的低停頓時間,又只能在很少的CPU(比如說1到2個)上運行時,這個特性就相當有用。
    4)何時使用CMS收集器?
    如果應(yīng)用程序需要更短的垃圾收集停頓時間并且能夠承擔在運行時和垃圾收集器共享處理器資源,那么就可以使用CMS收集器。(由于其并發(fā)性,在垃圾收集過程中CMS收集器將和應(yīng)用程序搶奪CPU周期。)通常來說,具有較大的長壽數(shù)據(jù)集并且運行在2個或多個CPU上的應(yīng)用程序,更容易受益于CMS收集器的使用。一個典型的例子就是Web服務(wù)器。對于任何需要低停頓時間的應(yīng)用程序來說,CMS收集器都值得考慮。對于年長代尺寸適中并且運行在單一處理器上的交互式應(yīng)用程序來說,使用CMS收集器同樣可能取得不錯的效果。
    5)CMS收集器的選用
    CMS收集器只能通過命令行選項“-XX:+UseConcMarkSweepGC”進行顯示的選用。如果希望CMS收集器在增量模式下運行,還需要通過命令行選項“-XX:+CMSIncrementalMode”啟用該模式。

    九、收集器、堆尺寸和虛擬機的自動選擇
    在J2SE 5.0中,根據(jù)應(yīng)用程序所運行的硬件平臺和操作系統(tǒng),垃圾收集器、堆尺寸和HotSpot虛擬機(客戶機或服務(wù)器)的缺省值被自動選定。這些自動的選擇不僅減少了對命令行選項的使用,而且還更好的滿足了不同類型應(yīng)用程序的需要。
    1)服務(wù)器級硬件(server-class machine,不使用“機器”這個詞是因為讀起來太拗口)的定義:
    服務(wù)器級硬件必須同時滿足以下兩個條件:
    ①擁有2個或以上的物理處理器
    ②擁有2GB或以上的物理內(nèi)存
    該定義適用于所有平臺,32位Windows平臺除外。
    2)服務(wù)器級硬件與非服務(wù)器級硬件下各項缺省值的比較:
    機器類型 虛擬機 垃圾收集器 堆尺寸初始值-Xms 堆尺寸最大值-Xmx
    服務(wù)器級硬件 服務(wù)器版 并行收集器 物理內(nèi)存的1/64,不超過1GB 物理內(nèi)存的1/4,不超過1GB
    非服務(wù)器級硬件 客戶機版 串行收集器 4MB 64MB
    注意:本節(jié)所涉及的堆尺寸指的是Java堆的大小,包括年幼代和年長代,但不包括永久代。  

    posted on 2011-10-30 20:47 paulwong 閱讀(346) 評論(0)  編輯  收藏 所屬分類: 性能優(yōu)化

    主站蜘蛛池模板: 在线观看亚洲免费视频| 亚洲av无码天堂一区二区三区| 自怕偷自怕亚洲精品| 免费福利在线播放| 亚洲精华液一二三产区| 久久亚洲精品无码观看不卡| 久草视频在线免费看| 狠狠色伊人亚洲综合网站色| 亚洲午夜精品一级在线播放放 | 最近在线2018视频免费观看| 亚洲人片在线观看天堂无码| 亚洲精品一级无码中文字幕| 美丽的姑娘免费观看在线播放| 中文字幕的电影免费网站| 亚洲成无码人在线观看| 久久亚洲国产精品五月天婷| 免费一级大黄特色大片| 免费v片在线观看视频网站| 久久狠狠躁免费观看| 免费无码又爽又刺激网站| 亚洲av片在线观看| 亚洲精品永久www忘忧草| 亚洲 另类 无码 在线| 国产成人免费在线| 亚洲av色香蕉一区二区三区 | 成人免费视频77777| 国产精品美女免费视频观看| 亚洲人成激情在线播放| 国产亚洲精品xxx| 国产午夜免费福利红片| 男女免费观看在线爽爽爽视频 | 亚洲av无码成h人动漫无遮挡| 精品国产麻豆免费网站| 亚洲免费闲人蜜桃| 日韩欧毛片免费视频| 亚洲成年人免费网站| 国产精品无码免费播放| 日韩中文字幕免费视频| a一级毛片免费高清在线| 国产日韩在线视频免费播放| 亚洲AV色无码乱码在线观看|