色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術(shù)文章
文章詳情頁

一篇帶你入門Java垃圾回收器

瀏覽:69日期:2022-08-10 14:38:02
目錄1 垃圾回收算法1-1 標(biāo)記清除算法算法概述算法思想1-2 標(biāo)記整理算法1-3 復(fù)制算法2 JVM分代回收算法2-1 概述2-2 分代垃圾回收示例2-3 分代垃圾回收的總結(jié)對象首先分配在伊甸園區(qū)域2-5 垃圾回收案例分析2 垃圾回收器2-1 垃圾回收器概述2-2 串行垃圾回收器2-3 吞吐量優(yōu)先的垃圾回收器2-4 響應(yīng)時間優(yōu)先的垃圾回收器(CMS垃圾回收器)總結(jié):

第一階段:串行垃圾回收器:jdk1.3.1之前Java虛擬機僅僅只支持Serial收集器

第二階段:并行垃圾回收器:隨著多核的出現(xiàn),Java引入了并行垃圾回收器,充分利用多核性能提升垃圾回收效率

第三階段:并發(fā)標(biāo)記清理回收器CMS:垃圾回收器可以和應(yīng)用程序同時運行,降低暫停用戶線程執(zhí)行的時間

第四階段:G1(并發(fā))回收器:初衷是在清理非常大的堆空間的時候能滿足特定的暫停應(yīng)用程序的時間,與CMS相比會有更少的內(nèi)存碎片

1 垃圾回收算法1-1 標(biāo)記清除算法算法概述

優(yōu)點:回收速度快

缺點:造成內(nèi)存碎片,無法分配大的連續(xù)空間。

算法思想

在Java9之前,Java默認(rèn)使用的垃圾回收器是ParallelGC,從Java9開始G1作為了默認(rèn)的垃圾回收器

一篇帶你入門Java垃圾回收器

step1: 第一次掃描,通過GC root對象判斷堆內(nèi)存中哪些對象可以進(jìn)行垃圾回收,進(jìn)行標(biāo)記。 step2: 第二次掃描, 將那些標(biāo)記的GC root對象進(jìn)行垃圾回收,只需要將起始內(nèi)存地址與終止內(nèi)存地址放入空閑內(nèi)存區(qū)就行。1-2 標(biāo)記整理算法

第一個依舊是標(biāo)記,第二步會進(jìn)行一個空間整理,從而不產(chǎn)生碎片。

優(yōu)點:避免了內(nèi)存碎片

缺點:對空間的整理使得效率比較低下。

一篇帶你入門Java垃圾回收器

1-3 復(fù)制算法

特點

將管理的內(nèi)存分為2塊區(qū)域,from區(qū)域與to區(qū)域,將那些不需要回收的對象從from區(qū)域拷貝到to區(qū)域。復(fù)制的過程中完成內(nèi)存區(qū)域的整理。之后交換from和to的指向。

優(yōu)點:不會產(chǎn)生內(nèi)存碎片

缺點:需要雙倍的內(nèi)存空間,內(nèi)存利用率不高,而且拷貝也需要時間。

一篇帶你入門Java垃圾回收器一篇帶你入門Java垃圾回收器一篇帶你入門Java垃圾回收器

1-4 三種垃圾回收算法總結(jié)

垃圾回收算法 優(yōu)點 缺點 標(biāo)記清除算法(Mark Sweep) 速度較快 產(chǎn)生內(nèi)存碎片 標(biāo)記整理算法(Mark Compact) 沒有內(nèi)存碎片 速度慢 復(fù)制算法(Copy) 沒有內(nèi)存碎片 需要占用雙倍內(nèi)存空間

注意:實際的JVM垃圾回收算法中上面的三種算法是綜合使用的。

2 JVM分代回收算法2-1 概述

Garden of Eden:伊甸園 garbage:垃圾

一篇帶你入門Java垃圾回收器

新生代主要由三部分內(nèi)容組成,分別是Eden區(qū),幸存區(qū)from,幸存區(qū)to。 通常情況下只有Eden區(qū)與幸存區(qū)from會存放數(shù)目,幸存區(qū)to只有垃圾回收時,復(fù)制對象會用到。堆內(nèi)存的新生代進(jìn)行一次垃圾回收(Minor GC),大部分對象都會都會被回收。

老年代通常存放一些經(jīng)常被使用的對象,一個對象如果經(jīng)歷多次垃圾回收仍然幸存,那么該對象會從新生代放入老年代。只有新生代內(nèi)存不足并且老年代內(nèi)存也不足的時候才會觸發(fā)full GC對老年代的對象進(jìn)行垃圾回收。

為什么需要進(jìn)行劃分?

實際環(huán)境中,對象的生命周期是不同的,老年代的對象生命周期比較長,可能很長時間才進(jìn)行一次垃圾回收。新生代的對象生命周期比較短,垃圾回收比較頻繁。這種分區(qū)法方便采用不同的垃圾回收算法更加有效的進(jìn)行垃圾回收。

2-2 分代垃圾回收示例

step1:程序剛剛開始運行,產(chǎn)生的對象先放入Eden區(qū),當(dāng)Eden區(qū)放不下的時候。

step2:對Eden區(qū)進(jìn)行Minor GC,并將沒有被垃圾回收的對象復(fù)制的幸存區(qū)To,然后交換幸存區(qū)To和幸存區(qū)From,第一次垃圾回收的最終的效果如下圖所示:

一篇帶你入門Java垃圾回收器

step3: 第一次Minor GC, Eden區(qū)又有空間可以分配給新的對象使用,經(jīng)過一段時間Eden又不夠用了,觸發(fā)第二次Minor GC, 這次垃圾會檢查Eden區(qū)以及幸存區(qū)From哪些對象可以存活,并將這些對象復(fù)制到幸存區(qū)To,然后交換幸存區(qū)To和幸存區(qū)From,這個時候Eden區(qū)又空了出來,可以放置新的對象。

一篇帶你入門Java垃圾回收器

實際垃圾回收過程中,JVM會對每個對象經(jīng)過垃圾回收幸存下來的次數(shù)進(jìn)行記錄,比如上圖中,幸存區(qū)的2個對象經(jīng)過垃圾回收的次數(shù)分別是1和2。

step4: 當(dāng)一些對象經(jīng)過垃圾回收的次數(shù)仍然幸存的次數(shù)達(dá)到一個閾值(說明這個對象價值比較高),那么這個對象會被移動到老年代。

一篇帶你入門Java垃圾回收器

極端情況考慮:Eden區(qū),from區(qū),老年區(qū)都已經(jīng)滿了?

一篇帶你入門Java垃圾回收器

此時會觸發(fā)Full GC(優(yōu)先Minor GC,Minor GC依舊內(nèi)存不夠)

2-3 分代垃圾回收的總結(jié)對象首先分配在伊甸園區(qū)域

新生代空間不足時,觸發(fā) minor gc,伊甸園和 from 存活的對象使用 copy復(fù)制到 to 中,存活的對象年齡加 1并且交換from to

minor gc 會引發(fā)stop the world,暫停其它用戶的線程,等垃圾回收結(jié)束,用戶線程才恢復(fù)運行暫停時間較短,由于新生代大部分對象都是垃圾,復(fù)制的對象很少,所以效率較高

當(dāng)對象壽命超過閾值時,會晉升至老年代,最大壽命是15(4bit,對象頭存儲)

當(dāng)老年代空間不足,會先嘗試觸發(fā) minor gc,如果之后空間仍不足,那么觸發(fā)full gc,STW的時間更長

Full GC 的stop the world的時間要比MInor GC時間長,老年代存活對象較多加上空間整理時間,所以停止時間會較長。如果Full GC后,空間仍然不足會觸發(fā)內(nèi)存不足的異常。

2-4 垃圾回收相關(guān)的虛擬機參數(shù)

垃圾回收器概述

參數(shù)含義 參數(shù) 備注 堆初始大小 -Xms堆最大大小 -Xmx 或 -XX:MaxHeapSize=size新生代大小 -Xmn 或 (-XX:NewSize=size + -XX:MaxNewSize=size ) NewSize是初始大小,MaxNewSize是最大大小。 幸存區(qū)比例(動態(tài)) -XX:InitialSurvivorRatio=ratio 和 -XX:+UseAdaptiveSizePolicy 幸存區(qū)的比例,默認(rèn)是8,假設(shè)新生代10M內(nèi)存,8M劃分給Eden區(qū),剩下的二等分,一份from,一份to。 幸存區(qū)比例 -XX:SurvivorRatio=ratio 動態(tài)調(diào)整幸存區(qū)比例 晉升閾值 -XX:MaxTenuringThreshold=threshold 用于動態(tài)調(diào)整幸存區(qū)比例 晉升詳情 -XX:+PrintTenuringDistribution 用于動態(tài)調(diào)整幸存區(qū)比例 GC詳情 -XX:+PrintGCDetails -verbose:gc 打印詳情信息 FullGC 前 MinorGC -XX:+ScavengeBeforeFullGC 默認(rèn)在Full GC 前進(jìn)行一次Minor GC 2-5 垃圾回收案例分析

情況1:什么都不放的情況

new generation:新生代 tenured generation:老年代

package cn.itcast.jvm.t2;import java.util.ArrayList;/** * 演示內(nèi)存的分配策略 */public class Demo2_1 { private static final int _512KB = 512 * 1024; private static final int _1MB = 1024 * 1024; private static final int _6MB = 6 * 1024 * 1024; private static final int _7MB = 7 * 1024 * 1024; private static final int _8MB = 8 * 1024 * 1024;//加入Java開發(fā)交流君樣:756584822一起吹水聊天 // -Xms20M -Xmx20M -Xmn10M : 堆初始與最大大小都是20M,新生代的大小為10M. // -XX:+UseSerialGC : 為了學(xué)習(xí)方便,采用這個垃圾回收器,默認(rèn)的垃圾回收器并不是這個。 // -XX:+PrintGCDetails -verbose:gc :打印詳細(xì)信息 // -XX:-ScavengeBeforeFullGC :在Full GC 前進(jìn)行 Minor GC. public static void main(String[] args) throws InterruptedException {new Thread(() -> { ArrayList<byte[]> list = new ArrayList<>(); list.add(new byte[_8MB]); list.add(new byte[_8MB]);}).start();System.out.println('sleep....');Thread.sleep(1000L); }}

情況1執(zhí)行結(jié)果

可以看到即使用戶沒有創(chuàng)建對象,系統(tǒng)對象也要占據(jù)一部分堆內(nèi)存空間。

Heap def new generation total 9216K, used 2341K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)// 新生代的空間總的大小為9216K,這里沒有把To空間給計算進(jìn)去,系統(tǒng)任務(wù)To的空間是分配是不可用的,所以不是10M,已經(jīng)使用了2341K,[]內(nèi)部則是內(nèi)存地址范圍。eden space 8192K, 28% used [0x00000000fec00000, 0x00000000fee49420, 0x00000000ff400000)//from space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000) to space 1024K, 0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000) tenured generation total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)// 老年代大小為10M,可以看到?jīng)]有任何空間使用 //加入Java開發(fā)交流君樣:756584822一起吹水聊天 the space 10240K, 0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000) Metaspace used 3394K, capacity 4496K, committed 4864K, reserved 1056768K class space used 378K, capacity 388K, committed 512K, reserved 1048576K

Java的內(nèi)存對象都是分配在堆上嗎

情況2:新生代堆空間放滿,觸發(fā)GC

public static void main(String[] args) throws InterruptedException {ArrayList<byte[]> list = new ArrayList<>();list.add(new byte[_7MB]); // 系統(tǒng)類占用2341K,加上new的7MB觸發(fā)垃圾回收 }

情況2執(zhí)行結(jié)果

[GC (Allocation Failure) [DefNew: 2342K->696K(9216K), 0.0029193 secs] 2342K->696K(19456K), 0.0029867 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] // GC:minor GC(新生代垃圾回收) FUll GC (老年代垃圾回收)// [Times: user=0.00 sys=0.00, real=0.00 secs] 垃圾回收執(zhí)行時間Heap def new generation total 9216K, used 8110K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000) eden space 8192K, 90% used [0x00000000fec00000, 0x00000000ff33d8c0, 0x00000000ff400000) from space 1024K, 67% used [0x00000000ff500000, 0x00000000ff5ae100, 0x00000000ff600000) to space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000) tenured generation total 10240K, used 0K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000) the space 10240K, 0% used [0x00000000ff600000, 0x00000000ff600000, 0x00000000ff600200, 0x0000000100000000) Metaspace used 3539K, capacity 4536K, committed 4864K, reserved 1056768K //加入Java開發(fā)交流君樣:756584822一起吹水聊天 class space used 395K, capacity 428K, committed 512K, reserved 1048576K

情況三: 新生代內(nèi)存隨著對象的增多放不下了

public static void main(String[] args) throws InterruptedException {ArrayList<byte[]> list = new ArrayList<>();list.add(new byte[_7MB]);list.add(new byte[_512KB]);list.add(new byte[_512KB]); }

執(zhí)行結(jié)果

新生代放不下,將新生代的對象放置到老年代。

[GC (Allocation Failure) [DefNew: 2342K->670K(9216K), 0.0022591 secs] 2342K->670K(19456K), 0.0023131 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [DefNew: 8678K->538K(9216K), 0.0061246 secs] 8678K->8354K(19456K), 0.0061637 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] Heap def new generation total 9216K, used 1132K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000) eden space 8192K, 7% used [0x00000000fec00000, 0x00000000fec94930, 0x00000000ff400000) from space 1024K, 52% used [0x00000000ff400000, 0x00000000ff486a00, 0x00000000ff500000) to space 1024K, 0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000) tenured generation total 10240K, used 7815K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000) the space 10240K, 76% used [0x00000000ff600000, 0x00000000ffda1f80, 0x00000000ffda2000, 0x0000000100000000) Metaspace used 3539K, capacity 4536K, committed 4864K, reserved 1056768K //加入Java開發(fā)交流君樣:756584822一起吹水聊天 class space used 395K, capacity 428K, committed 512K, reserveed 1048576K

情況四:一開始直接分配大于新生代的內(nèi)存,如果老年代放的下,則直接放到老年代

public static void main(String[] args) throws InterruptedException {ArrayList<byte[]> list = new ArrayList<>();list.add(new byte[_8MB]); }

執(zhí)行結(jié)果

Heap def new generation total 9216K, used 2507K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000) eden space 8192K, 30% used [0x00000000fec00000, 0x00000000fee72ca8, 0x00000000ff400000) from space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000) to space 1024K, 0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000) tenured generation total 10240K, used 8192K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000) the space 10240K, 80% used [0x00000000ff600000, 0x00000000ffe00010, 0x00000000ffe00200, 0x0000000100000000) Metaspace used 3539K, capacity 4536K, committed 4864K, reserved 1056768K class space used 395K, capacity 428K, committed 512K, reserved 1048576K

小結(jié)

當(dāng)內(nèi)存比較緊張的時候,即新生代內(nèi)存放不下的時候,有時候會直接將對象分配到老年代,或者直接在回收次數(shù)較少(未達(dá)到15次)的情況下,直接將新生代對象弄到老年代。【資料獲取】

2 垃圾回收器2-1 垃圾回收器概述名稱 特點 適合場景 目標(biāo) 新生代 老年代 串行垃圾回收器 單線程 堆內(nèi)存小,適合個人電腦(cpu個數(shù))采用復(fù)制的垃圾回收算法 采用標(biāo)記+整理的垃圾回收算法 吞吐量優(yōu)先垃圾回收器 多線程 堆內(nèi)存大,多核CPU 并行,讓單位時間內(nèi)STW的時間最短 復(fù)制算法 標(biāo)記+拷貝 響應(yīng)時間優(yōu)先的垃圾回收器(簡稱CMS) 多線程 堆內(nèi)存大,多核CPU 并發(fā),盡可能讓單次STW最短 復(fù)制算法 標(biāo)記清除算法產(chǎn)生內(nèi)存碎片需要退化成單線程的垃圾整理回收器

CMS垃圾回收器后來被G1垃圾回收器取代。

2-2 串行垃圾回收器

開啟串行垃圾回收器的JVM參數(shù)

-XX:+UseSerialGC = Serial + SerialOld// Serial:工作在新生代,采用復(fù)制的垃圾回收算法// SerialOld:工作在老生代,采用標(biāo)記+整理的垃圾回收算法

一篇帶你入門Java垃圾回收器

總結(jié):觸發(fā)垃圾回收時,讓多個線程在一個安全點停下來,然后使用單線程的垃圾回收器去進(jìn)行垃圾回收,垃圾回收完成后,再讓其他線程運行。

2-3 吞吐量優(yōu)先的垃圾回收器

開啟吞吐量優(yōu)先的垃圾回收器的JVM參數(shù)

開啟/關(guān)閉的參數(shù)

默認(rèn)的多線程垃圾回收器,前者是開啟新生代回收器,采用復(fù)制算法,后者是開啟老年代回收器,采用標(biāo)記+拷貝算法。下面選項只要開啟一個,那么另外一個也會開啟。

-XX:+UseParallelGC , -XX:+UseParallelOldGC

開啟自適應(yīng)動態(tài)調(diào)整新生代的大小,晉升閾值

-XX:+UseAdaptiveSizePolicy

二個指標(biāo)調(diào)整的參數(shù)(ParallelGC會根據(jù)設(shè)定的指標(biāo)去調(diào)整堆的大小到達(dá)下面期望設(shè)定的目標(biāo))指標(biāo)1)1/(1+ratio) = 垃圾回收的時間/總的運行時間

ratio默認(rèn)值時99,即垃圾回收的時間不超過總時間1%。但一般設(shè)為19。【資料獲取】如果達(dá)不到目標(biāo),ParallelGC會調(diào)整堆內(nèi)存大小來達(dá)到這個目標(biāo),通常是調(diào)大,這樣垃圾回收的次數(shù)會減少,從而提高吞吐量

-XX:GCTimeRatio=ratio

指標(biāo)2)每次垃圾回收的時間限制( 最大暫停的毫秒數(shù))

默認(rèn)值是200ms顯然將堆內(nèi)存空間變小有助于減少每次垃圾回收的時間

-XX:MaxGCPauseMillis=ms

總結(jié):顯然指標(biāo)1)與指標(biāo)2)是有沖突的。

-XX:ParallelGCThreads=n //垃圾回收并行的線程數(shù)目

一篇帶你入門Java垃圾回收器

小結(jié)

采用多線程方式進(jìn)行垃圾回收,垃圾回收的線程數(shù)目通常根據(jù)CPU的核數(shù)進(jìn)行設(shè)置。在垃圾回收階段,并行的垃圾回收線程會充分占用CPU。在非垃圾回收階段,用戶線程會充分利用CPU資源。

2-4 響應(yīng)時間優(yōu)先的垃圾回收器(CMS垃圾回收器)

缺點:采用的標(biāo)記清除算法產(chǎn)生內(nèi)存碎片需要退化成單線程的垃圾整理回收器,造成響應(yīng)時間變長。

開啟的JVM參數(shù)

注意這個是并發(fā)的采用標(biāo)記清除算法的垃圾回收,這里區(qū)別于之前的垃圾回收器,該垃圾回收器能夠在進(jìn)行垃圾回收的同時運行其他非垃圾回收線程(也存在時間階段需要停止,但不是所有階段停止)。

老年代并發(fā)的垃圾回收器會出現(xiàn)失敗的情況,這時老年代垃圾回收器會退化成單線程的垃圾回收器(SerialOld)

-XX:+UseConcMarkSweepGC // use concurrent mark sweep(會產(chǎn)生垃圾碎片) 工作在老年代的垃圾回收器-XX:+UseParNewGC// 工作在新生代的垃圾回收器

重要的初始參數(shù)

-XX:ParallelGCThreads=n// 并行的垃圾回收線程數(shù),通常等于CPU的核心數(shù)(垃圾回收并行階段)-XX:ConcGCThreads=threads // 并發(fā)的線程數(shù)目,通常設(shè)為并行垃圾回收線程數(shù)的1/4(垃圾回收并發(fā)階段)

其他參數(shù)

-XX:CMSInitiatingOccupancyFraction=percent // 執(zhí)行垃圾回收的內(nèi)存占比,預(yù)留空間給浮動垃圾-XX:+CMSScavengeBeforeRemark// 在重新標(biāo)記前,對新生代進(jìn)行垃圾回收,減少并發(fā)清理的垃圾對象,+開啟,-關(guān)閉

一篇帶你入門Java垃圾回收器

浮動垃圾是指并發(fā)清理過程中用戶線程新產(chǎn)生的垃圾,需要等待下次并發(fā)清理。

并發(fā)工作流程概述:

step1:老年代發(fā)生內(nèi)存不存的現(xiàn)象。 step2:ConcMarkSweepGC會進(jìn)行一個初始標(biāo)記動作(初始標(biāo)記需要STW即阻塞非垃圾回收線程),初始標(biāo)記只標(biāo)記根對象,所以速度非常快,暫停時間也非常短。 step3:完成初始標(biāo)記后,之前阻塞的線程又可以運行了,這個時候垃圾回收線程進(jìn)行并發(fā)標(biāo)記。 step4:并發(fā)標(biāo)記結(jié)束后,需要再次阻塞非垃圾回收線程,進(jìn)行一個所謂的重新標(biāo)記, step5:重新標(biāo)記完成后,阻塞的線程又可以運行了。垃圾回收線程也并發(fā)的清理垃圾對象。總結(jié):

初始標(biāo)記與重新標(biāo)記需要阻塞線程。 在并發(fā)階段,由于垃圾回收線程占用資源,所以系統(tǒng)的吞吐量會受到一定的影響,但是系統(tǒng)的響應(yīng)速度由于并發(fā)執(zhí)行不會受到垃圾回收的明顯影響(相比較其他垃圾回收器,STW時間只需要進(jìn)行初始標(biāo)記與重新標(biāo)記,并且能夠不阻塞其他線程進(jìn)行垃圾的標(biāo)記與清除)。

最后,祝大家早日學(xué)有所成,拿到滿意offer,快速升職加薪,也請多多關(guān)注好吧啦網(wǎng)的其他文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 国产精品无打码在线播放9久 | 国产成人教育视频在线观看 | 久热草在线 | 99久久伊人一区二区yy5099 | 日韩久久久精品首页 | 91青青国产在线观看免费 | 在线欧美自拍 | 亚洲性网站 | 特黄a大片免费视频 | 夜夜爽影院 | 国产色在线观看 | 国内精品久久久久久久久久影视 | 国产精品合集一区二区 | 成年人视频在线免费播放 | 日本美女作爱 | 国产草草影院 | 青青热久久国产久精品 | 亚洲精品国产一区二区在线 | 日本精品久久久久久久久免费 | 在线看国产 | 色妇女影院 | 九九视频高清视频免费观看 | 日韩在线一区二区三区免费视频 | 国产高清一区二区三区视频 | 免费人成在线观看 | 日韩高清在线不卡 | 国产精品亚洲片在线不卡 | 国产免费成人在线视频 | 一级片美国 | 美女被免费视频的网站 | 日韩毛片欧美一级a网站 | 国产欧美精品一区二区三区四区 | 欧美日韩国产亚洲一区二区 | 欧美特黄一级 | 欧美一级www | 欧美日韩精品一区二区另类 | 大黄一级片| 亚洲精品成人7777在线观看 | 黄色美女视频免费 | 精品高清国产a毛片 | 日韩欧美一区二区在线观看 |