精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

來聊聊 JVM 中安全點(diǎn)的概念

開發(fā)
本文從JVM工作原理引出安全點(diǎn)的作用、工作方式、常見配置和一些性能表現(xiàn)上的風(fēng)險(xiǎn)點(diǎn),從而給出一些比較經(jīng)典的實(shí)踐案例,希望對(duì)你有幫助。

近期在分享關(guān)于synchronized關(guān)鍵字的文章的時(shí)候提到了一個(gè)關(guān)于安全點(diǎn)的概念,有讀者反饋這塊知識(shí)點(diǎn)講的有些潦草,遂以此文簡(jiǎn)單介紹一下JVM中關(guān)于安全點(diǎn)的概念。

一、詳解safepoint基本概念

1. 什么是安全點(diǎn)?為什么需要安全點(diǎn)

在正式講解安全點(diǎn)之前,我們不妨復(fù)習(xí)一下JVM中垃圾回收的基本過程,我們以CMS垃圾回收器為例,其垃圾回收過程在完成GC Roots查找與收集之后就會(huì)按照如下步驟執(zhí)行:

  • 初始標(biāo)記
  • 并發(fā)回收
  • 最終標(biāo)記(重新標(biāo)記)
  • 并發(fā)清除

要知道固定可作為GC Roots的節(jié)點(diǎn)主要是:

  • 全局引用:例如常量或者靜態(tài)變量。
  • 執(zhí)行上下文即棧幀中的變量表。

對(duì)于現(xiàn)代java應(yīng)用而言,光是方法區(qū)就可能有數(shù)百上千兆,所以對(duì)于這些起源的引用也并非一件容易的事情。這也就意味著JVM在進(jìn)行垃圾回收時(shí)并不能通過逐個(gè)掃描檢查來實(shí)現(xiàn)。 就目前主流的JVM來說,針對(duì)根節(jié)點(diǎn)枚舉基本都是采用空間換時(shí)間的策略,也就是使用一組OopMap,全稱為"Object Pointer Map"(對(duì)象指針映射),本質(zhì)上就是一個(gè)位圖索引,它會(huì)通過以下兩個(gè)時(shí)機(jī)完成對(duì)象信息的緩存:

  • 類加載完成后,hotSpot就會(huì)基于類的偏移量信息計(jì)算出來并緩存。
  • JIT階段也會(huì)在特定的時(shí)機(jī)(這一點(diǎn)后續(xù)會(huì)詳細(xì)說明)計(jì)算出棧或寄存器中的那些位置是引用,并將其緩存。

如此一來,下次進(jìn)行根枚舉時(shí)就可以直接基于OopMap高效完成:

但是java進(jìn)程的運(yùn)行的瞬息萬變的,可能此刻的對(duì)象在下一刻就不可用,下一刻又有新的對(duì)象誕生,這種引用關(guān)系的實(shí)時(shí)變化亦或者說導(dǎo)致OopMap內(nèi)容變化的指令是非常多的,若針對(duì)每一個(gè)指令都設(shè)置對(duì)應(yīng)的oopMap,那么內(nèi)存的開銷是非常高昂的。

所以就有了安全點(diǎn)(safepoint)的概念,這也就是我們上文所提及的特定的位置,基于這個(gè)設(shè)定,用戶的程序僅僅會(huì)在特定的情況下生成oopMap,同理在垃圾回收時(shí),也要求所有線程達(dá)到安全點(diǎn)后才能夠暫停并進(jìn)入STW從而開始進(jìn)行初始標(biāo)記、最終標(biāo)記等操作:

例如下面這段代碼:

Object o=new Object();

對(duì)應(yīng)匯編碼如下,可以看到0x00000000031ffb8f的call指令,它指明偏移量40-852處有一個(gè)普通對(duì)象指針Oop(Ordinary Object Pointer):

0x00000000031ffb80: mov    $0xf5,%edx
  0x00000000031ffb85: mov    %ecx,%ebp
  0x00000000031ffb87: mov    %rbx,0x28(%rsp)
  0x00000000031ffb8c: data16 xchg %ax,%ax
  0x00000000031ffb8f: callq  0x00000000030957a0  ; OopMap{[40]=Oop off=852}
                                                ;*new  ; - java.lang.String::<init>@58 (line 205)
                                                ; - java.lang.String::substring@52 (line 1933)
                                                ;   {runtime_call}

2. JVM如何讓線程跑到最近的安全點(diǎn)

對(duì)于安全點(diǎn)上的線程中斷策略,大體來說是有兩種:

  • 搶占式:當(dāng)需要進(jìn)入安全點(diǎn)時(shí),JVM會(huì)主動(dòng)掛起所有的用戶線程,如果線程未在安全點(diǎn)則等到該線程進(jìn)入安全點(diǎn)進(jìn)入安全點(diǎn)并完成中斷。這種做法最大的缺點(diǎn)就是時(shí)間不可控即很可能存在性能不穩(wěn)定亦或者吞吐量的波動(dòng),所以截至目前還有那款虛擬機(jī)采用搶占式的方式完成線程中斷。
  • 主動(dòng)式:這種方式是讓線程去維護(hù)一個(gè)標(biāo)志位,需要進(jìn)入安全點(diǎn)時(shí)修改該變量,用戶線程就會(huì)在合適的時(shí)機(jī)檢查這個(gè)變量值,如果這個(gè)值為真時(shí)就進(jìn)入安全點(diǎn)。

3. 線程什么時(shí)候需要進(jìn)入安全點(diǎn)

除了常見的垃圾回收標(biāo)記觸發(fā)STW使得所有線程需要進(jìn)入安全點(diǎn)以外,對(duì)應(yīng)的進(jìn)入安全點(diǎn)的時(shí)機(jī)還有:

  • 使用jstat、jmap、jstack等命令,為保證監(jiān)控堆棧信息的實(shí)時(shí)正確性,所有線程需要STW并進(jìn)入安全點(diǎn)暫停。
  • JDK8默認(rèn)情況下定時(shí)進(jìn)入安全點(diǎn),保證一些需要進(jìn)入安全點(diǎn)的操作能夠及時(shí)運(yùn)行。
  • JIT編譯代碼優(yōu)化例如:OSR(棧上替換即一種運(yùn)行時(shí)替換棧幀的技術(shù))或者去優(yōu)化即Bailout(將JIT編譯后的代碼回退,解釋器模式),因?yàn)榭赡艽嬖趫?zhí)行指令的變化,線程就需要進(jìn)入安全點(diǎn)。
  • java agent需要對(duì)類進(jìn)行增強(qiáng)導(dǎo)致類重新定義,需要修改類的相關(guān)信息,所以需要進(jìn)入安全點(diǎn)。
  • 高并發(fā)情況下,鎖升級(jí)機(jī)制會(huì)涉及偏向鎖撤銷,需要進(jìn)入STW檢查每個(gè)線程的使用狀態(tài),所以也需要進(jìn)入安全點(diǎn)。

4. JVM如何保證線程高效進(jìn)入安全點(diǎn)

我們以線程運(yùn)行JIT編譯好的代碼為例,它的設(shè)計(jì)與實(shí)現(xiàn)步驟為:

  • JVM初始化一個(gè)異常處理器,專門捕獲對(duì)應(yīng)的page fault缺頁(yè)中斷異常。
  • JIT編譯代碼期間,會(huì)基于我們上述的規(guī)則在特定位置插入一條精簡(jiǎn)的指令,作為安全點(diǎn)檢查。
  • VM線程通知當(dāng)前線程進(jìn)入安全點(diǎn),將線程內(nèi)部維護(hù)的內(nèi)存頁(yè)即polling page設(shè)置為不可讀。
  • 線程執(zhí)行這條機(jī)器碼指令發(fā)現(xiàn)內(nèi)存頁(yè)不可讀,觸發(fā)缺點(diǎn)中斷。
  • 異常處理器捕獲這個(gè)異常,線程進(jìn)入安全點(diǎn)。

對(duì)應(yīng)的我們也給出這段精簡(jiǎn)的匯編碼指令,即test %eax,0x160100 ; {poll}這段指令,這段指令本質(zhì)上就是執(zhí)行poll操作檢查安全點(diǎn),嘗試訪問線程內(nèi)存頁(yè)對(duì)應(yīng)地址為0x160100,如果發(fā)現(xiàn)不可訪問則觸發(fā)缺頁(yè)中斷進(jìn)入安全點(diǎn):

0x01b6d627: call   0x01b2b210         ; OopMap{[60]=Oop off=460}      
                                       ;*invokeinterface size      
                                       ; - Client1::main@113 (line 23)      
                                       ;   {virtual_call}      
 0x01b6d62c: nop                       ; OopMap{[60]=Oop off=461}      
                                       ;*if_icmplt      
                                       ; - Client1::main@118 (line 23)      
 0x01b6d62d: test   %eax,0x160100      ;   {poll}      
 0x01b6d633: mov    0x50(%esp),%esi      
 0x01b6d637: cmp    %eax,%esi

5. 如何設(shè)置安全點(diǎn)

而這個(gè)輪詢操作的合適的時(shí)機(jī)也就是觸發(fā)安全點(diǎn)的時(shí)機(jī),對(duì)于安全點(diǎn)的選定不能太過于頻繁導(dǎo)致過分增加內(nèi)存的負(fù)荷,如果進(jìn)入安全點(diǎn)的選定太少同樣也會(huì)導(dǎo)致線程無法及時(shí)進(jìn)入安全點(diǎn)而導(dǎo)致未能及時(shí)GC而OOM,所以我們對(duì)于安全點(diǎn)的選定一定要符合能夠讓程序長(zhǎng)時(shí)間的運(yùn)行為標(biāo)準(zhǔn):

無界循環(huán)或者大循環(huán):對(duì)于長(zhǎng)時(shí)間的while(true)或者以long類型為輪詢次數(shù)的for循環(huán),JVM會(huì)插入安全點(diǎn)保證循環(huán)能夠在需要停頓時(shí)及時(shí)停頓:

for (long i = 0; i < 10_0000_0000; i++) {
                counter.getAndAdd(1);
                //safe point
}
            
while (true){
                counter.getAndAdd(1);
                //safe point
 }

在執(zhí)行方法調(diào)用返回之前:

private boolean function() {
        //do something
        return true;
        //safe point 
    }

可能拋出異常的位置,例如下面這段代碼:

public static void main(String[] args)  {
        int result = 10 / 0;
    }

對(duì)應(yīng)的匯編碼如下,可以看到因?yàn)樗銛?shù)可能存在異常,它就在0x00000000033f0695設(shè)置了一個(gè)test安全點(diǎn)檢查:

0x00000000033f066c: mov    $0xa,%eax         ; 將被除數(shù)10加載到eax寄存器
0x00000000033f0671: mov    $0x0,%esi         ; 將除數(shù)0加載到esi寄存器(準(zhǔn)備觸發(fā)除零異常)
0x00000000033f0676: cmp    $0x80000000,%eax  ; 檢查被除數(shù)是否為Integer.MIN_VALUE(-2^31)
0x00000000033f067c: jne    0x00000000033f068d ; 如果不是則跳轉(zhuǎn)到常規(guī)除法流程
0x00000000033f0682: xor    %edx,%edx         ; 清零edx寄存器(特殊溢出處理路徑)
0x00000000033f0684: cmp    $0xffffffff,%esi  ; 檢查除數(shù)是否為-1(配合前面對(duì)MIN_VALUE的檢查)
0x00000000033f0687: je     0x00000000033f0690 ; 如果是-1則跳過除法(避免MIN_VALUE/-1溢出)
0x00000000033f068d: cltd                     ; 將eax符號(hào)位擴(kuò)展到edx(準(zhǔn)備64位被除數(shù))
0x00000000033f068e: idiv   %esi              ; 執(zhí)行有符號(hào)除法eax/esi(此處會(huì)觸發(fā)除零異常)
                                              ; 對(duì)應(yīng)Java代碼:int result = 10 / 0;
                                              ; 隱式異常處理分支:dispatches to 0x00000000033f069c
0x00000000033f0690: add    $0x30,%rsp        ; 調(diào)整棧指針(清理?xiàng)?0x00000000033f0694: pop    %rbp              ; 恢復(fù)調(diào)用者的基址指針
0x00000000033f0695: test   %eax,-0x28b059b(%rip) ; 安全點(diǎn)檢查:{poll_return}
                                              ; 檢查線程本地polling page是否可訪問
                                              ; 不可訪問則進(jìn)入安全點(diǎn)處理

6. 用一次GC解釋不同狀態(tài)的線程如何進(jìn)入safepoint

當(dāng)VM線程(JVM內(nèi)部的一種特殊的系統(tǒng)線程)需要觸發(fā)GC時(shí),它需要所有的線程都進(jìn)入安全點(diǎn),從而實(shí)現(xiàn)STW:

  • 線程正在運(yùn)行字節(jié)碼:這種情況也就是常規(guī)的情況,這解釋器會(huì)查看線程是否被設(shè)置為poll armed,如果為真則將其block阻塞。
  • 線程運(yùn)行JIT編譯好的代碼:JIT會(huì)在指定位置插入安全點(diǎn)檢查,如果需要進(jìn)入安全點(diǎn),JVM則會(huì)將線程內(nèi)部維護(hù)的內(nèi)存頁(yè)即polling page設(shè)置為不可讀,當(dāng)線程在安全點(diǎn)檢查時(shí)感知到這一點(diǎn)之后,就會(huì)直接將內(nèi)存block。
  • 線程正在運(yùn)行native代碼:VM線程不會(huì)等待該線程進(jìn)入阻塞狀態(tài),而是將線程設(shè)置為poll armed,當(dāng)線程執(zhí)行完成native代碼并返回時(shí)看到這個(gè)標(biāo)識(shí),如果還是需要停在safepoint,則會(huì)直接block阻塞。
  • 正在阻塞的線程,這種情況下線程就會(huì)一直阻塞,直到所有線程完成safepoint對(duì)應(yīng)的操作。
  • 正在執(zhí)行狀態(tài)切換,或者VM線程狀態(tài)(即執(zhí)行虛擬機(jī)線程正在工作的一種狀態(tài))的線程:這種情況下安全點(diǎn)檢查相關(guān)的代碼會(huì)不斷輪詢?cè)摼€程,直到該線程因?yàn)闋顟B(tài)切換或者鎖定safepoint checked monitor(安全點(diǎn)監(jiān)視鎖)完成阻塞。

需要注意這一小節(jié),筆者強(qiáng)調(diào)的是如何進(jìn)入安全點(diǎn)(各個(gè)線程如何進(jìn)入安全點(diǎn)),而不是何處插入安全點(diǎn)(插入安全點(diǎn)時(shí)機(jī)的選擇),讀者在閱讀本文時(shí)一定要梳理清楚插入安全時(shí)機(jī)設(shè)置和進(jìn)入安全點(diǎn)的時(shí)機(jī)設(shè)置的區(qū)別。

二、實(shí)踐-基于主線程休眠了解安全點(diǎn)的工作過程

1. 代碼示例

這段代碼比較簡(jiǎn)單,兩個(gè)子線程異步累加源自類,主線程休眠1s后輸出自己休眠的時(shí)長(zhǎng):

AtomicInteger counter = new AtomicInteger(0);

        Runnable runnable = () -> {
            for (int i = 0; i < 10_0000_0000; i++) {
                counter.getAndAdd(1);
            }
            System.out.println(Thread.currentThread().getName() + "運(yùn)行結(jié)束,counter:" + counter.get());
        };

        Thread t1 = new Thread(runnable, "t1");
        Thread t2 = new Thread(runnable, "t2");
        t1.start();
        t2.start();
        //主線程開始休眠
        long begin = System.currentTimeMillis();
        System.out.println("主線程開始休眠");
        Thread.sleep(1000);
        //休眠結(jié)束后,等待其他線程進(jìn)入安全點(diǎn)才開始結(jié)束休眠,所以輸出耗時(shí)19s
        long cost = System.currentTimeMillis() - begin;
        System.out.println("主線程結(jié)束休眠,耗時(shí):" + cost + "ms");

很多讀者可能認(rèn)為主線程打印的耗時(shí)差不多是1s,但事與愿違,輸出的結(jié)果竟然是30s:

主線程開始休眠
t1運(yùn)行結(jié)束,counter:2000000000
t2運(yùn)行結(jié)束,counter:2000000000
主線程結(jié)束休眠,耗時(shí):29956ms

由上述我們講解進(jìn)入,主線程調(diào)用native休眠返回后,程序因?yàn)槟撤N原因進(jìn)入全局安全點(diǎn),而兩個(gè)子線程因?yàn)槭怯薪缪h(huán)未能進(jìn)入安全點(diǎn),最終導(dǎo)致主線程長(zhǎng)時(shí)間等待兩個(gè)子線程進(jìn)入安全而導(dǎo)致休眠打印變長(zhǎng):

2. 基于日志印證執(zhí)行流程

對(duì)此我們基于-XX:+SafepointTimeout -XX:SafepointTimeoutDelay=2000參數(shù),查看進(jìn)入安全點(diǎn)超過2s后,主線程(包括其他未強(qiáng)調(diào)的用戶線程)在等待那些線程進(jìn)入安全點(diǎn)。

很明顯,從輸出結(jié)果來看所有線程都在等待兩個(gè)子線程進(jìn)入安全點(diǎn):

更進(jìn)一步,我們添加-XX:+PrintSafepointStatistics參數(shù),查看所有線程進(jìn)入安全點(diǎn)的耗時(shí),可以發(fā)現(xiàn):

  • JVM內(nèi)部非安全點(diǎn)的線程自旋等待進(jìn)入安全點(diǎn)時(shí)間和主線程休眠時(shí)間基本一致。
  • 同步所有線程進(jìn)入安全點(diǎn)時(shí)間block和上述休眠結(jié)束的耗時(shí)基本一致。

由此印證的問題根因:子線程未能及時(shí)進(jìn)入安全點(diǎn):

最后一個(gè)問題,這個(gè)觸發(fā)安全點(diǎn)的時(shí)機(jī)是什么呢?

通過-XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal打印JVM參數(shù)可以發(fā)現(xiàn)下面這個(gè)參數(shù),查閱資料我們可以知曉該參數(shù)GuaranteedSafepointInterval,會(huì)默認(rèn)1s讓程序進(jìn)入一次全局安全點(diǎn):

所以我們最終得出根因,假設(shè)主線程在程序啟動(dòng)100ms進(jìn)入休眠,程序?qū)?yīng)的執(zhí)行步驟為:

  • 代碼執(zhí)行,JVM啟動(dòng),由于GuaranteedSafepointInterval參數(shù)配置為1000ms,所以在1s時(shí)需要設(shè)置一個(gè)安全點(diǎn)標(biāo)識(shí)位,讓所有用戶線程更新oopMap。
  • 主線程在1100ms時(shí)完成了1s的休眠準(zhǔn)備退出native的sleep,檢查安全點(diǎn)標(biāo)識(shí)為真因?yàn)槿表?yè)異常進(jìn)入安全點(diǎn)。
  • 兩個(gè)子線程因?yàn)橛薪缪h(huán)沒能進(jìn)入安全點(diǎn)繼續(xù)循環(huán)。
  • 主線程和其他用戶線程等待t1、t2完成循環(huán)。

3. 優(yōu)化思路

基于上述的分析,我們可以得出導(dǎo)致主線程休眠過長(zhǎng)的時(shí)間的主要原因:

  • 由于GuaranteedSafepointInterval定時(shí)觸發(fā)安全點(diǎn),導(dǎo)致主線程休眠結(jié)束后進(jìn)入安全點(diǎn)。
  • 主線程進(jìn)入安全點(diǎn)期間,子線程因?yàn)橛薪缪h(huán)而未能進(jìn)入安全點(diǎn)。

所以,基于原因1我們可以通過-XX:+UnlockDiagnosticVMOptions -XX:GuaranteedSafepointInterval=0強(qiáng)制關(guān)閉進(jìn)入安全點(diǎn),得到如下效果:

主線程開始休眠
主線程結(jié)束休眠,耗時(shí):1014ms

對(duì)于原因2,將有界循環(huán)改為long,讓JIT識(shí)別到這個(gè)大循環(huán)而插入安全點(diǎn):

三、關(guān)于安全點(diǎn)更進(jìn)一步的理解

1. 關(guān)于安全點(diǎn)的調(diào)優(yōu)建議

  • 高并發(fā)微服務(wù)的場(chǎng)景下建議關(guān)閉偏向鎖-XX:-UseBiasedLocking。
  • 避免有界循環(huán)可以在循環(huán)到一定次數(shù)時(shí),設(shè)置Thread.sleep(0)輔助進(jìn)入安全點(diǎn)。
  • int長(zhǎng)有界循環(huán)改為long,讓JIT為其插入安全點(diǎn)。
  • 優(yōu)化有界但是耗時(shí)長(zhǎng)的循環(huán)代碼。
  • 關(guān)閉定時(shí)進(jìn)入安全點(diǎn)-XX:+UnlockDiagnosticVMOptions -XX:GuaranteedSafepointInterval=0。

2. JDK11對(duì)于安全點(diǎn)的優(yōu)化

考慮到定時(shí)進(jìn)入安全點(diǎn)的非必要性和高并發(fā)場(chǎng)景下的阻塞風(fēng)險(xiǎn),jdk11默認(rèn)情況下已經(jīng)將該參數(shù)關(guān)閉,對(duì)此我們可以鍵入jinfo -flag GuaranteedSafepointInterval <pid>查看。

輸出結(jié)果如下,可以看到筆者將項(xiàng)目改為JDK11之后,對(duì)應(yīng)的參數(shù)值設(shè)置為0,即不定時(shí)進(jìn)入安全點(diǎn):

3. RocketMQ中對(duì)于安全點(diǎn)的優(yōu)化

基于上述的調(diào)優(yōu)建議,我們也給出RocketMQ對(duì)于安全點(diǎn)的優(yōu)化,以4.8.0版本為例,MappedFile為避免零拷貝循環(huán)寫入操作的耗時(shí),它會(huì)定時(shí)的調(diào)用Thread.sleep(0);讓線程調(diào)用native方法從而到達(dá)安全點(diǎn),保證需要時(shí)進(jìn)入STW完成GC:

public void warmMappedFile(FlushDiskType type, int pages) {
        long beginTime = System.currentTimeMillis();
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        int flush = 0;
        long time = System.currentTimeMillis();
        for (int i = 0, j = 0; i < this.fileSize; i += MappedFile.OS_PAGE_SIZE, j++) {
            byteBuffer.put(i, (byte) 0);
            //......

            // prevent gc
            //定期休眠,保證及時(shí)進(jìn)入安全點(diǎn),不阻塞其他需要進(jìn)入安全點(diǎn)的線程
            if (j % 1000 == 0) {
                log.info("j={}, costTime={}", j, System.currentTimeMillis() - time);
                time = System.currentTimeMillis();
                try {
                    Thread.sleep(0);
                } catch (InterruptedException e) {
                    log.error("Interrupted", e);
                }
            }
        }

       //......
    }

后續(xù)版本, 為了保證更加合理的進(jìn)入安全點(diǎn),這塊代碼也被直接優(yōu)化為long的長(zhǎng)循環(huán),讓JIT自行優(yōu)化,在合適的位置插入安全點(diǎn)保證線程能夠及時(shí)進(jìn)入安全點(diǎn)配合需要STW等工作:

責(zé)任編輯:趙寧寧 來源: 寫代碼的SharkChili
相關(guān)推薦

2025-06-30 07:10:00

JavaJVM線程

2025-07-09 07:30:00

2024-03-15 08:04:30

G1CMSJVM

2023-08-16 08:00:00

MSP安網(wǎng)絡(luò)安全

2023-11-09 09:38:50

自動(dòng)駕駛模型

2023-09-01 08:59:57

2024-02-04 09:00:00

向量查詢數(shù)據(jù)檢索MyScale

2020-02-24 21:43:36

avaJVM 級(jí)鎖線程安全

2024-12-30 08:03:08

2020-11-20 07:51:02

JavaSPI機(jī)制

2024-02-21 08:19:54

2023-07-14 12:28:07

JVM優(yōu)化操作

2023-06-26 07:57:49

2025-02-24 10:07:09

Redis節(jié)點(diǎn)遷移集群

2023-04-19 09:05:44

2023-07-31 07:48:43

Java內(nèi)存虛擬機(jī)

2023-04-24 14:54:09

JVM性能調(diào)優(yōu)

2023-01-08 13:46:49

2022-06-05 00:15:31

驗(yàn)證身份網(wǎng)絡(luò)

2024-08-07 08:22:27

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

57pao国产一区二区| 青青草视频在线免费直播| 国产精品视频免费观看www| 成人亚洲一区| 九九久久九九久久| 成人全视频高清免费观看| 激情文学综合插| 五月天激情小说| 精品精品国产高清a毛片牛牛| 色在线视频观看| 亚洲av无日韩毛片久久| 一本色道亚洲精品aⅴ| 17videosex性欧美| 亚洲一区二区三区免费观看| 亚洲精品视频在线观看网站| 国产一二区在线观看| 91久久国产精品91久久性色| 亚洲日本欧美| 久久亚洲国产成人精品性色| 国产视频精品一区二区三区| 99久久99久久精品国产片果冰| 7788色淫网站小说| 欧美天天综合网| 国产亚洲一区二区手机在线观看 | 亚洲丝袜在线观看| 亚洲精品在线观看视频| 中文字幕久久精品一区二区| 青青草精品视频在线观看| 欧美日韩国产中文字幕 | 中文字幕一区免费在线观看 | 一本到12不卡视频在线dvd| 青青青视频在线播放| 欧美成人伊人久久综合网| 最新精品国偷自产在线| 免费人成视频在线播放| 在线观看精品自拍私拍| 亚洲国产日韩在线| 日韩精品一区二区三区国语自制| 奇门遁甲1982国语版免费观看高清| 精久久久久久久久久久| 国产精品免费无遮挡无码永久视频| 国产精品视频在线观看| 久久99国产精品久久99果冻传媒| 亚洲系列第一页| 国产欧美日韩一区二区三区| 国产精品久久久久久久免费软件| 国产chinasex对白videos麻豆| 国产精品视频在线播放| 成人网男人的天堂| 密臀av在线| 中文字幕亚洲乱码| 亚洲欧美日韩另类| 狠狠色丁香久久婷婷综合_中| 成人不用播放器| 亚洲巨乳在线观看| 精品污污网站免费看| 美女一区二区在线观看| 免费一级全黄少妇性色生活片| 欧美人在线观看| 国产高清不卡二三区| 性xxxfreexxxx性欧美| 影音先锋资源av| 中文字幕在线精品| 日本不卡一区二区三区| 91黄色在线| 欧美日韩人妻精品一区在线| 日本精品视频在线| 99视频精品免费视频| 日本免费一区二区三区最新| 欧美亚洲一二三区| 欧美少妇bbb| 欧美亚洲高清| 国产婷婷一区二区三区久久| 欧日韩免费视频| 亚洲美女性视频| 亚洲精品一区二区妖精| 亚洲aⅴ乱码精品成人区| 少妇人妻互换不带套| 亚洲国产精品热久久| 亚洲专区欧美专区| 自拍亚洲图区| 成年人一级黄色片| 色播五月综合| 欧美一卡二卡三卡四卡| 久久精品国产999大香线蕉| heyzo一区| 国产乱了高清露脸对白| 欧美亚洲另类在线| 欧美国产亚洲另类动漫| 免费看av成人| 欧洲免费在线视频| 成人在线免费观看网址| 亚洲黄色在线看| 婷婷综合久久| 91社区在线| 香蕉在线观看视频| 国产精品第100页| 欧美性猛交xxxx免费看| 日精品一区二区| 精品av导航| 国产又色又爽又黄又免费| 日韩一区免费观看| 精品美女一区二区三区| 成人手机在线视频| 国产激情欧美| 一级做a爰片久久毛片16| 日本中文字幕精品—区二区| 91人成网站www| 日本道在线观看一区二区| 日韩**一区毛片| www.91精品| 99久久精品国产一区色| 亚洲精品无码一区二区| 成人激情视频在线| 在线播放欧美女士性生活| 久久激情婷婷| 成人小电影网站| aaa在线视频| 视频在线观看免费高清| 精品产品国产在线不卡| 日韩精品一区二区三区四区 | 国产suv精品一区二区68| 成人免费自拍视频| 日韩精品资源二区在线| 亚洲国产高清在线观看视频| 在线一区电影| 日本中文字幕伦在线观看| 麻豆一区产品精品蜜桃的特点| 精品乱色一区二区中文字幕| 欧美少妇bbb| 国产一区三区三区| 欧美精品羞羞答答| av片在线观看永久免费| 91视频免费网址| 中文字幕成人一区| 九九精品在线视频| 欧美狂野另类xxxxoooo| 久久精品国产99| julia一区二区三区中文字幕| 亚洲无码精品在线观看| 一区二区免费在线观看视频| 在线码字幕一区| 欧美孕妇毛茸茸xxxx| 91精品国产综合久久久蜜臀粉嫩| 国产精品第四页| 国产精品老牛| 国产一区一区| 免费在线观看av| 久草国产在线视频| 91亚洲精品久久久蜜桃借种| 一道本在线观看视频| 国产精品黄视频| 亚洲欧美日韩一区在线| 欧美日韩免费看| 国产精品538一区二区在线| 91精品丝袜国产高跟在线| av网站大全在线观看| www香蕉视频| 国产这里有精品| 中文字幕5566| 中文久久久久久| 国产精品久久激情| 欧美性xxxxxxx| 久久精品日韩一区二区三区| 1024精品一区二区三区| 欧美尿孔扩张虐视频| 日韩精品黄色| 午夜精品久久久久久久蜜桃| 欧洲美熟女乱又伦| 91免费黄视频| 日韩免费av电影| 国产精品久久久久久久久久直播 | 老司机免费视频| 国产爆乳无码一区二区麻豆| 欧美一区二区三区成人久久片 | 欧美天天影院| 欧美一区二区少妇| 蜜芽tv福利在线视频| 水莓100在线视频| 中文字字幕在线中文乱码| 国产在线观看免费视频软件| 污污视频网站免费观看| 色就是色欧美| 欧美一二三四五区| 成人亚洲激情网| 欧美精品videosex极品1| 日韩欧美一二三四区| 亚洲妇女屁股眼交7| 国产精品女人毛片| 国产亚洲成年网址在线观看| www.亚洲激情.com| 久久99精品国产91久久来源| 国产精品99久久久久| 日韩影院在线观看| 一本色道久久| 伊人久久综合影院| 国产精品igao视频网网址不卡日韩| 2021天堂中文幕一二区在线观| 黄色网页在线免费观看| www.亚洲资源| 18免费在线视频| 天天干天天摸天天操| 黄色片视频免费| 日韩欧美性视频| 国产无遮挡裸体免费视频| 极品颜值美女露脸啪啪| 免费成人蒂法网站| 中文字幕a在线观看| 成年人看片网站| 成人午夜激情av| 黄色录像a级片| 亚洲av成人片色在线观看高潮| 久操视频免费看| wwwwxxxx国产| 国产一区二区三区四区五区六区 | 天堂av在线免费| 男人的天堂在线视频| 五月天福利视频| 在线观看黄色av| freexxx性亚洲精品| 亚洲精品福利电影| 国产精品亚洲一区二区在线观看| 清纯唯美激情亚洲| 欧美成人首页| 国产一级久久| 久久综合五月| 国产色综合一区| 欧美伊人久久大香线蕉综合69 | 成人午夜剧场视频网站| 日本黄色动态图| 五月天综合视频| jizz中文字幕| 日韩久久久久久久久久| 国产高清av在线| 刘亦菲一区二区三区免费看| 超碰国产精品一区二页| 黑人久久a级毛片免费观看| 欧美成人精品午夜一区二区| 日韩高清影视在线观看| 国产一区视频在线观看免费| 国产精一区二区三区| 久久精品亚洲精品国产欧美| 亚洲成人资源网| 国产99亚洲| brazzers在线观看| eeuss鲁一区二区三区| 日韩黄色三级| 精品国产一区二区三区不卡蜜臂 | 国产a久久精品一区二区三区 | 久久欧美中文字幕| 欧美人狂配大交3d怪物一区| 欧美精品videos性欧美| 国产福利久久| 国产超级av在线| 一出一进一爽一粗一大视频| 怡红院男人的天堂| 免费观看成年人视频| 黄色网址视频在线观看| 4438五月综合| 亚州av乱码久久精品蜜桃| 国产成人自拍高清视频在线免费播放| 亚洲图片一区二区| 在线观看日韩av先锋影音电影院| 亚洲国产高清福利视频| 欧美福利视频在线| 91免费电影网站| 日本日本19xxxⅹhd乱影响| 2014亚洲天堂| 无码人妻丰满熟妇精品 | 亚洲一级不卡视频| 亚洲白虎美女被爆操| 日本91av在线播放| 日韩av片在线看| 日本黄色免费片| 国内精品久久久久久久久久| 欧美1234区| 四季av在线一区二区三区 | 在线观看欧美一区| 91精彩刺激对白露脸偷拍| 天天干视频在线| 久草在线综合| 91视频在线看| 免费观看在线色综合| 国内成+人亚洲+欧美+综合在线| 亚洲人成电影网站色mp4| 不卡av电影在线观看| 国产精品久久久一区| 男人日女人下面视频| 国产乡下妇女做爰| 美女尤物在线视频| 欧美~级网站不卡| 亚洲人精品一区| 欧美成人免费va影院高清| 欧美日韩一区在线观看视频| 特黄特色免费视频| 国产综合在线播放| 成人在线黄色| 91精品国产视频| 五月天国产精品| 国产精品扒开腿做| 久久久无码中文字幕久...| 日本xxx在线播放| 肉体视频在线| 亚洲电影影音先锋| 性做久久久久久免费观看欧美| 欧美日韩高清区| 另类小说色综合| 天堂av中文在线资源库| 欧美高清不卡| 色婷婷精品久久二区二区蜜臀av| 国产精选久久久久久| 亚洲77777| 无码人妻精品一区二区50| gay欧美网站| 色小子综合网| 亚洲欧美激情视频在线观看一区二区三区| 少妇久久久久久| 亚洲一区影院| 国产成人精品亚洲| heyzo欧美激情| 国产女主播在线一区二区| 久久久精品免费视频| 麻豆传媒一区| 秋霞精品一区二区三区| 欧美xxxx在线| 亚洲乱码国产乱码精品精可以看| 51久久精品夜色国产麻豆| 热久久精品免费视频| 黄色国产在线| 一本色道88久久加勒比精品| 日本精品一级二级| 91精品久久久久久久久久| 我要看一级黄色大片| 色婷婷av一区二区三区之红樱桃 | 最新日韩在线| 亚洲国产综合色| 粉嫩精品一区二区三区在线观看| 蜜乳av中文字幕| 欧美电影免费观看网站| 国产精品久久久久久久久免费桃花 | 久久人妻无码一区二区| 日本在线观看视频网站| 欧美日本成人| 欧美日韩精品在线| 久久精品午夜一区二区福利| 一级免费黄色录像| 精品国产18久久久久久二百| www.在线成人| 91福利视频网| 亚洲欧洲综合网| 久久国产精品免费一区二区三区| 国产欧美一区二区三区鸳鸯浴| 国产日韩欧美中文| 欧美精品久久久久性色| 国产黄大片在线观看| 成人免费福利片| 91午夜理伦私人影院| 欧美日韩国产精品一区二区三区| 福利一区和二区| 国产精品传媒入口麻豆| 极品校花啪啪激情久久| 亚洲 欧美 视频| 中文精品久久| 日韩久久精品成人| 日本中文字幕一级片| 亚洲AV无码一区二区三区少妇| 欧美福利一区| 最近2019免费中文字幕视频三 | 都市激情久久综合| 国产成人在线免费观看| 97视频免费看| 久草视频在线资源| 精品国产亚洲一区二区在线观看| 亚洲高清视频在线| 中文字幕欧美人与畜| 丁香在线视频| 91在线精品秘密一区二区| 亚洲综合在线小说| 懂色av蜜臀av粉嫩av分享吧最新章节| 亚洲承认在线| 69影院欧美专区视频| 精品少妇久久久| 国产精品theporn| 久久久电影免费观看完整版| 欧美在线一级片| 99亚洲男女激情在线观看| 黑人巨大精品欧美一区二区三区 | 国产午夜精品理论片a级探花| 小早川怜子一区二区三区| 狂野欧美xxxx韩国少妇| 91精品福利在线| 粗暴91大变态调教| 在线a免费看| 91天堂素人约啪| 国产精品手机在线| 青青草免费在线| 中文字幕乱码日本亚洲一区二区| 国产精品美女久久久久av福利| 欧洲av在线播放| 国产在线麻豆精品观看|