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

淺析JVM invokedynamic指令和Java Lambda語法

開發 前端
Lambda表達式語言特性引入Java語言后,賦予了Java語言更便捷的函數式編程魔力(相對匿名內部類),同時也讓其更簡潔,畢竟Java代碼寫起來啰嗦這點一直被開發者們廣泛詬病。

一、導語

盡管近年來JDK的版本發布愈發敏捷,當前最新版本號已經20+,但是日常使用中,JDK8還是占據了統治地位。

圖片圖片

你發任你發,我用Java8:【Jetbrains】2023 開發者生態系統現狀 - https://www.jetbrains.com/zh-cn/lp/devecosystem-2023/java/

JDK8如此旺盛的生命力,與其優異的兼容性、穩定性和足夠日常開發使用的語言特性有極大的關系,這其中最引人矚目的語言特性莫過于Lambda表達式。

Lambda表達式語言特性引入Java語言后,賦予了Java語言更便捷的函數式編程魔力(相對匿名內部類),同時也讓其更簡潔,畢竟Java代碼寫起來啰嗦這點一直被開發者們廣泛詬病。

本文將從JVM和Java兩個層面著手,和大家一起深入解析Lambda表達式。

二、Java和JVM的關系

JVM是HLLVM(高級語言虛擬機),其參考物理計算機體系架構,設計、實現了一套特定領域虛擬指令集,即:字節碼指令。利用上述虛擬指令集作為中間層,將上層高級語言和底層體系架構解耦以規避繁瑣、復雜的平臺兼容性問題,以實現【一次編譯,處處運行】。

Java是基于JVM提供的虛擬指令集,設計、實現的一種供開發者使用的高級語言。通過配套的編譯器和標準庫,將文本格式的Java代碼編譯成符合JVM指令集規范的二進制文件,交付到JVM執行。

Java是一種運行在JVM平臺上的高級語言,但是JVM平臺絕不是只能運行Java語言。任何人都可以設計自己的語言語法,只要能按JVM規范編譯成合法的JVM字節碼,即可在JVM上運行(用Java命令)。

計算機科學領域的任何問題,都可以通過增加一個中間層來解決。

圖片圖片

沒有無源之水,Java語言層面的特性,除非是純語法糖,不然一定離不開特定JVM特性的支撐。Lambda是Java8語言特性,那支撐它的便是JVM invokedynamic指令。

三、JVM指令:invokedynamic

在Java7之前,JVM提供了如下4種【方法調用】指令:

圖片圖片

上述4種字節碼指令各自有不同的使用場景,但是有一個共同的特點:目標方法一定需要在【編譯期】確定。如下圖,編譯后4種指令的參數都指定了目標方法所在的類和簽名以供運行時鏈接、動態分派。

圖片圖片

圖片圖片

這個特點一方面保證了JVM語言類型安全,另一方面也限制了JVM平臺對動態類型高級語言的支持。比如想讓JavaScript、Python等動態語言代碼編譯成JVM字節碼運行在JVM平臺上的開銷會比較大,性能也會比較差。

為了解決上述問題, Java7引入了一條新的虛擬機指令:invokedynamic。這是自JVM 1.0以來第一次引入新的虛擬機指令,invokedynamic與其他 invoke*指令不同的是它允許由應用級的代碼來決定方法解析(鏈接、分派)。

所謂的【應用級的代碼來決定方法解析】需要對照之前的invoke*指令來理解。之前的4種invoke*指令,在編譯期就必須要明確目標方法并hardcode到字節碼中,JVM在運行時直接解析、鏈接、動態分派硬編碼指定的目標方法。而invokedynamic指令通過回調機制來獲取需要調用的目標方法。即先調用業務自定義回調方法做方法決策(解析、鏈接),再調用其返回的目標方法。筆者稱之為【兩階段調用】。

偽代碼對比如下:

圖片圖片

MethdoHandle為示意,后文有詳述。

偽字節碼偽字節碼

invokevirtual指令直接調用目標方法,invokedynamic直接調用回調方法,再調用回調方法返回的方法句柄。

傳統的invoke*指令直接調用字節碼中指定的目標方法,如Son.testMethod1,invokedynamic指令在調用時,先調用字節碼中指定的回調方法,如Son.dynamicMethodCallback,然后再調用回調方法(hook)返回的方法引用。

而上述dynamicMethodCallback即為【應用級的代碼或者我們常說的業務代碼】,可以在不影響性能的前提下,靈活的干預JVM方法解析、鏈接的過程。

總結來說,所謂應用級的代碼其實也是一個方法,在這里這個方法被稱為引導方法(Bootstrap Method),簡稱 BSM。invokedynamic執行時,BSM先被調用并返回一個 CallSite(調用點)對象,這個對象就和 invokedynamic鏈接在一起。以后再執行這條invokedynamic指令都不會創建新的 CallSite 對象。CallSite就是一個 MethodHandle(方法句柄)的holder,方法句柄指向一個調用點真正執行的方法。

一階段:調用引導方法確定并緩存CallSite(MethodHandle)

二階段:調用CallSite(MethodHandle)

字節碼指令比較low level,除字節碼業務插樁場景外,字節碼指令序列的構造、編排一般都由【高級語言編譯器】來根據語言語法規則自動完成,如javac。

某種意義上有點類似Java【動態代理】機制,都是通過調用橫切來動態橋接、靈活決策目標方法。

四、方法句柄:MethodHandle

前面我們知道invokedynamic指令支持通過業務層面自定義的BSM來靈活的決策被調用的目標方法,也就是上述的【一階段】。BSM方法的返回值就是【二階段】調用的方法。

但是和C、Python等語言不同,Java中方法/函數不是一等公民,也就是在Java中無法將【方法變量】作為方法返回值。

為了解決這個問題,Java標準庫提供了一個新的類型MethodHandle,用于實現類似C語言中的方法指針、JavaScript/Python中方法變量的能力。該API和反射API呈現的能力相似,但是性能更好。

圖片圖片

上述為MethodHandle API的基本使用,該課題展開又是一篇長文。總之,我們可以用MethodHandle來作為【方法變量】,變相的將【Java方法】提升為【一等公民】,從而可以在BSM中用Java代碼實現動態編排、決策,返回合適的方法指針。這也是上述invokedynamic+BSM機制能夠成立的一個基礎。

詳見:秒懂Java之方法句柄(MethodHandle) (https://blog.csdn.net/ShuSheng0007/article/details/107066856)

上述【一階段】調用的本質就是得到一個特定的MethodHandle(方法指針/方法引用),【二階段】調用就是調用這個MethodHandle。

五、Lambda表達式簡介

Java的Lambda表達式,是傳統的【匿名內部類】特性在特定場景下的平替特性。所謂的特定場景,即我們熟知的FunctionalInterface。

當【匿名內部類】匿名實現的是一個FunctionalInterface時,可以用Lambda表達式平替。

示例如下:

圖片圖片

函數式接口(Functional Interface)就是一個有且僅有一個抽象方法,但是可以有多個非抽象方法的接口。

Java 不會強制要求你使用 @FunctionalInterface 注解來標記你的接口是函數式接口,然而,作為API作者,你可能傾向使用@FunctionalInterface指明特定的接口為函數式接口,這只是一個設計上的考慮,可以讓用戶很明顯的知道一個接口是函數式接口。

Java Lambda表達式在語法層面有兩種形式:行內代碼塊、方法引用。

圖片圖片

但是在編譯產物中,行內Lambda最終會被提取到獨立的靜態方法中。也就是說,在字節碼層面只有【方法引用】一種Lambda形式。

圖片圖片

圖片圖片

如上圖反編譯結果,兩個行內Lambda中的代碼在編譯后被提取到兩個自動生成的方法lambda$main$0、lambda$main$1,后續Lambda表達式的處理流程都可以收斂,無需區分對待。

六、Lambda表達式實現

Lambda表達式具體的實現涉及類文件結構、字節碼指令結構、標準庫等多個方面的內容,千頭萬緒。也想不出來什么通俗易懂的敘述角度,只能是枯燥的對照著字節碼分析了。

圖片圖片

如上圖,mian方法中聲明了3個Lambda表達式,反編譯字節碼可以看到字節碼指令流如下:

圖片圖片

0 iconst_3
 1 istore_1
 2 iconst_3
 3 newarray 10 (int)
 5 dup
 6 iconst_0
 7 iconst_1
 8 iastore
 9 dup
10 iconst_1
11 iconst_2
12 iastore
13 dup
14 iconst_2
15 iconst_3
16 iastore
17 invokestatic #2 <java/util/stream/IntStream.of : ([I)Ljava/util/stream/IntStream;>
20 invokedynamic #3 <applyAsInt, BootstrapMethods #0>
25 invokeinterface #4 <java/util/stream/IntStream.map : (Ljava/util/function/IntUnaryOperator;)Ljava/util/stream/IntStream;> count 2
30 iload_1
31 invokedynamic #5 <applyAsInt, BootstrapMethods #1>
36 invokeinterface #4 <java/util/stream/IntStream.map : (Ljava/util/function/IntUnaryOperator;)Ljava/util/stream/IntStream;> count 2
41 invokedynamic #6 <applyAsInt, BootstrapMethods #2>
46 invokeinterface #4 <java/util/stream/IntStream.map : (Ljava/util/function/IntUnaryOperator;)Ljava/util/stream/IntStream;> count 2
51 invokeinterface #7 <java/util/stream/IntStream.sum : ()I> count 1
56 istore_2
57 return

3個lambda表達式對應3條invokedynamic指令:

圖片圖片

第一個lambda表達式比較簡單且典型,后續我們以其為抓手展開分析。

invokedynamic指令參數

invokedynamic指令參數結構如下:

圖片圖片

jvms-6.5.invokedynamic (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokedynamic)

invokedynamic指令需要指定其期待BSM返回的方法特征(出入參類型)和BSM方法引用。該參數以CONSTANT_InvokeDynamic_info結構存放在類文件的常量池結構中,invokedynamic用兩個byte寬度的常量池索引號指定。

CONSTANT_InvokeDynamic_info {
    u1 tag;
    u2 bootstrap_method_attr_index;
    u2 name_and_type_index;
}

圖片圖片

對照字節碼我們可知,Lambda1相關的invokedynamic指定的CONSTANT_InvokeDynamic_info序號為3,得到如下內容:

圖片圖片

圖片圖片

期望的方法名稱和描述符

該invokedynamic指令期望BSM0方法返回一個如下特征的方法引用:

IntUnaryOperator anyName();

沒有入參,返回值類型為IntUnaryOperator的MethodHandle。

為什么是返回IntUnaryOperator類型呢?因為IntStream的map方法需要的參數是IntUnaryOperator類型。

圖片圖片

換句話說,該invokedynamic指令希望相應的BSM返回一個IntUnaryOperator的工廠方法句柄,然后invokedynamic指令再調用這個方法句柄,創建出一個map方法需要的IntUnaryOperator類型的參數。

BSM方法序號

BSM方法序號指定了當前invokedynamic指令使用的BSM方法在BSM方法表中的索引。

通俗來說,類文件中有一個數組,數組名稱叫BootstrapMethods。其結構如下:

BootstrapMethods_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 num_bootstrap_methods;
    {   u2 bootstrap_method_ref;
        u2 num_bootstrap_arguments;
        u2 bootstrap_arguments[num_bootstrap_arguments];
    } bootstrap_methods[num_bootstrap_methods];
}

圖片圖片

圖片圖片

圖片圖片

該invokedynamic指令指定的BSM為BSM數組中的第一個BSM。

圖片圖片

BSM方法

圖片圖片

圖片圖片

BSM方法參數

該BSM數據結構指定了3個編譯期固定的、靜態的BSM方法參數:

圖片圖片

第一、第三個參數指定了預期的函數式接口(FunctionInterface)的特征:入參為int、出參為int。即上述IntUnaryOperator。

圖片圖片

第二個參數是一個靜態方法引用。如上述,Lambda表達式在編譯時會被提取到一個自動生成的方法中。

圖片圖片

圖片圖片

至此,invokedynamic指令具有的發起【一階段調用】的上下文如下:

  1. 具體的一階段調用的BSM方法:java.lang.invoke.LambdaMetafactory#metafactory
  2. IntStream.map方法需要的參數類型:IntUnaryOperator
  3. 編譯器(javac)編譯產生的包含Lambda表達式代碼內容的靜態方法:lambda$main$0(I)I

接下來就是調用java.lang.invoke.LambdaMetafactory#metafactory方法,傳遞上述必要的上下文參數,接受metafactory方法返回的IntUnaryOperator applyAsInt()類型的MethodHandle并調用該MethodHandle,繼而得到IntStream.map方法需要的參數:IntUnaryOperator。

LambdaMetafactory#metafactory

圖片圖片

如上述,invokedynamic指令調用上述metafactory方法,對照字節碼信息,可以得到如下具體參數表格:

圖片圖片

LambdaMetafactory根據上述上下文,使用ASM庫,動態生成了一個如下所示的IntUnaryOperator適配類,用于橋接Lambda表達式代碼塊到IntUnaryOperator類型。

添加-Djdk.internal.lambda.dumpProxyClasses=.啟動參數,JDK會將生成的適配函數式接口的類源碼輸出到工作目錄中。

構造CallSite

圖片圖片

java.lang.invoke.InnerClassLambdaMetafactory#buildCallSite

生成FunctionalInterface適配類后,基于適配類創建MethodHandle。該MethodHandle體現的代碼邏輯類似如下Java代碼:

圖片圖片

至此,invokedynamic【一階段】調用已經完成,invokedynamic指令獲取到了由LambdaMetafactory#metafactory作為BSM動態決策、動態生成的IntUnaryOperator適配類的【工廠方法】(以CallSite包裝的MethodHandle的形式)。

二階段調用

【一階段調用】已經完成,返回了動態決策產生的CallSite對象,getTarget方法可以獲取上述的IntUnaryOperator適配類的【工廠方法】。

圖片圖片

至此,invokedynamic指令可以通過如下偽代碼,創建IntStream.map方法需要的IntUnaryOperator實例。

IntUnaryOperator intUnaryOperator = (IntUnaryOperator)callSite.getTarget().invoke()

Lambda1的整個運行時解析、鏈接流程完成。

七、Lambda表達式性能

圖片圖片

經過上述分析我們可以知道,Lambda1這種無狀態的、沒有捕獲外部變量(閉包)的Lambda表達式的開銷是很小的,只會在第一次調用時動態生成橋接的適配類,實例化后就通過ConstantCallSite緩存。后續所有的調用都不會再重新生成適配類、實例化適配類。

但是,Lambda2則不同,因為Lambda捕獲、依賴了(閉包)外部變量num,那么這個表達式就是有狀態的。雖然同樣只是會在第一次調用時動態生成橋接的適配類,但是每一次調用都會使用num變量重新實例化一個新的適配類實例。這種場景下,其在性能和形式上就已經和傳統的【匿名內部類】沒有太大差別了。

Lambda3本質上和Lambda1一樣,只不過不需要Java編譯器在編譯時將Lambda代碼語句抽取成獨立的方法。

八、Lambda表達式和final變量

圖片圖片

當Lambda表達式閉包捕獲的局部變量num在方法內可變時,編譯器會提示編譯錯誤。這不是JVM的限制,而是Java語言層面的限制。筆者認為,這種限制沒有技術上的原因,而是Java語言設計者刻意的借助編譯器在阻止你犯錯。

假設沒有這個限制,那么Lambda表達式就變成了重構不友好的【位置相關】的代碼塊。

換句話說,下面兩種代碼執行結果是不一樣的:

圖片圖片

Lambda捕獲的num的值為5;

圖片圖片

Lambda捕獲的num的值為3;

如果沒有類似的編譯約束,當我們有心或無意的在復雜的業務邏輯中進行了類似的代碼調整時,極易出錯且難以排查。

九、總結

提筆的時候立意高遠,想著要盡可能通俗詳盡的寫清楚所有涉及的技術點,但是越寫越覺得事情不簡單,最后只能是把博客標題從【深入剖析】修改為【淺析】。這塊內容牽涉的面太廣,筆者沒有能力也沒有精力介紹到事無巨細、面面俱到,只能為大家拋磚引玉,大家可以配合后文【參考資料】多梳理、多實驗,同時在評論區批評指正。

  1. invokedynamic指令不是業務開發者使用的。invokedynamic指令可以用來實現Lambda語法,但是它不是只能用來實現Lambda語法。這個指令對于JVM語言開發者比如Kotlin、Groovy、JRuby、Jython等會比較重要。
  2. 沒有捕獲外部變量(閉包)的Lambda表達式性能和直接調用沒有差別。
  3. 捕獲外部變量(閉包)的Lambda表達式性能理論上和【匿名內部類】范式一樣,每次調用都會創建一個對象(最壞情況)。

本文使用的反編譯工具為:jclasslib Bytecode Viewer

(https://plugins.jetbrains.com/plugin/9248-jclasslib-bytecode-viewer)

十、附錄

自動生成的Lambda2適配類

// $FF: synthetic class
final class LambdaTest$$Lambda$2 implements IntUnaryOperator {
    private final int arg$1;


    private LambdaTest$$Lambda$2(int var1) {
        this.arg$1 = var1;
    }


    private static IntUnaryOperator get$Lambda(int var0) {
        return new LambdaTest$$Lambda$2(var0);
    }


    @Hidden
    public int applyAsInt(int var1) {
        return LambdaTest.lambda$main$1(this.arg$1, var1);
    }
}

自動生成的Lambda3適配類

// $FF: synthetic class
final class LambdaTest$$Lambda$3 implements IntUnaryOperator {
    private LambdaTest$$Lambda$3() {
    }


    @Hidden
    public int applyAsInt(int var1) {
        return LambdaTest.add(var1);
    }
}

參考:

  • Oracle-Java虛擬機規范(JDK8)--https://docs.oracle.com/javase/specs/jvms/se8/html/
  • Oracle-Java語言規范(JDK8)-https://docs.oracle.com/javase/specs/jls/se8/html/index.html
  • JVM系列之:JVM是怎么實現invokedynamic的? | HeapDump性能社區-https://heapdump.cn/article/3573623
  • Java 虛擬機:JVM是怎么實現invokedynamic的?(上)-https://cloud.tencent.com/developer/article/1787369
  • Java 虛擬機:JVM是怎么實現invokedynamic的?(下)-https://cloud.tencent.com/developer/article/1787371
  • 【stackoverflow】What is a bootstrap method?-https://stackoverflow.com/questions/30733557/what-is-a-bootstrap-method
  • Java中普通lambda表達式和方法引用本質上有什么區別?-https://www.zhihu.com/question/51491241/answer/126232275
  • 理解 invokedynamic-https://juejin.cn/post/6844903503236710414
  • https://www.cnblogs.com/wade-luffy/p/6058087.html
  • 09 | JVM是怎么實現invokedynamic的?(下)-深入拆解Java虛擬機-極客時間-https://time.geekbang.org/column/article/12574
責任編輯:武曉燕 來源: 得物技術
相關推薦

2023-02-15 19:07:30

Java字節碼指令

2009-09-17 09:09:50

Lambda表達式Linq查詢

2021-06-27 06:25:14

代碼優化技巧Java

2016-09-07 20:56:24

2009-09-14 13:44:14

Lambda ExprC# Lambda

2013-03-29 11:09:17

JVM內存

2009-08-27 11:43:31

C#語法

2009-08-14 00:30:09

C#條件編譯指令

2010-09-30 15:19:33

2009-08-18 12:52:33

C#枚舉類型

2023-09-01 08:59:57

2020-05-14 10:47:13

Android Java 8

2015-04-09 10:18:21

網卡配置

2013-01-05 02:19:50

JavaLambda表達式JVM

2010-09-07 10:33:04

CSS

2009-07-06 12:49:33

JSP編譯器

2009-09-17 09:20:45

C#操作XML

2009-07-02 11:34:42

JSP指令JSP開發

2010-01-21 09:34:57

C++語法

2009-07-27 13:34:15

ASP.NET編程
點贊
收藏

51CTO技術棧公眾號

亚洲天堂中文字幕| 一区二区不卡| 欧美无砖砖区免费| 激情五月五月婷婷| 四季av日韩精品一区| 日本中文字幕一区二区视频| 久久亚洲精品毛片| 国产精品无码一区二区三区免费| se69色成人网wwwsex| 亚洲激情男女视频| 日韩成人av网站| 精品国自产在线观看| 性久久久久久| 欧美巨乳美女视频| 国产综合精品久久久久成人av| 日韩精品中文字幕一区二区| 色播五月激情综合网| 国产成人永久免费视频| 午夜伦理在线| 91蜜桃网址入口| 亚洲xxxx在线| 亚洲影视一区二区| 米奇777在线欧美播放| 欧美精品一区在线播放| 国产18无套直看片| 色综合www| 欧美精品一区二| 国产又黄又猛的视频| 欧美黑人粗大| 婷婷综合另类小说色区| 久久免费看毛片| 韩国三级av在线免费观看| 成人网在线播放| 亚洲综合日韩在线| 在线亚洲欧美日韩| 奇米影视在线99精品| 欧美亚洲激情在线| 日本少妇久久久| 欧美视频福利| 欧美人与性动交a欧美精品| 欧美成人短视频| 国产在线观看91一区二区三区| 日韩av在线一区二区| 中文字幕人妻一区二区三区| 国产美女精品视频免费播放软件 | 成人免费毛片xxx| 国产一区二区欧美| 亚洲少妇激情视频| 香蕉视频久久久| 精品国产91| 国产一区二区三区在线观看视频| theav精尽人亡av| 波多野结衣欧美| 精品成人佐山爱一区二区| www.在线欧美| 国产欧美韩日| 五月天婷婷在线观看| 成人爱爱电影网址| 国产欧美日韩综合一区在线观看| 亚洲欧洲一二三| 欧洲美女亚洲激情| 精品国产亚洲一区二区三区大结局| 欧美午夜精品久久久久久孕妇| 日本xxxx黄色| 国产999精品在线观看| 欧美一区二区性放荡片| 男人添女人荫蒂国产| 国产精品白丝一区二区三区| 亚洲精品第一国产综合精品| 91久久免费视频| 成人午夜av| 伦伦影院午夜日韩欧美限制| 国产一级视频在线观看| 一本色道88久久加勒比精品| 热久久免费国产视频| 亚洲午夜无码久久久久| 激情综合色综合久久| 粉嫩av免费一区二区三区| 天天综合网在线观看| 国产亲近乱来精品视频| 精品国产无码在线| 俺来俺也去www色在线观看| 偷窥少妇高潮呻吟av久久免费| 欧美成人免费高清视频| 国产亚洲精品精品国产亚洲综合| 91精品在线一区二区| 成人做爰69片免费| 国产欧美日韩在线观看视频| 久久精品视频在线观看| 国产对白videos麻豆高潮| 久久精品毛片| 一级成人国产| 亚洲视频axxx| 卡通动漫亚洲综合| 一区二区高清| 亚洲综合在线小说| 你懂的在线网址| 亚洲欧美另类小说视频| 亚洲中文字幕无码av永久| 桃子视频成人app| 91精品国产欧美日韩| 亚洲综合自拍网| 亚洲欧美在线专区| 国产成人激情小视频| 成人久久久精品国产乱码一区二区 | 999精彩视频| 99精品国产一区二区三区2021| 亚洲欧美日韩天堂| 精品小视频在线观看| 蜜桃精品视频在线| 久久涩涩网站| 黄网av在线| 欧美日韩国产精选| 亚洲午夜久久久久久久久红桃 | 女人扒开屁股爽桶30分钟| 亚洲成人高清| 一区二区三区国产在线观看| 日本学生初尝黑人巨免费视频| 麻豆精品新av中文字幕| 久久一区二区精品| 超级碰碰不卡在线视频| 91精品国产综合久久香蕉麻豆| 受虐m奴xxx在线观看| 激情久久中文字幕| 亚洲综合中文字幕68页| 米奇精品一区二区三区| 欧美中文字幕一区| 亚洲精品国产一区黑色丝袜| 亚洲激情亚洲| 国产精品v欧美精品v日韩| 久cao在线| 欧美人妖巨大在线| 五月婷婷六月香| 玖玖精品视频| 日本高清不卡三区| 黑人巨大精品| 亚洲欧洲国产一区| 亚洲欧美一区二区三区在线观看| 99视频一区二区三区| 欧美亚洲黄色片| 日韩三级av高清片| 久久97久久97精品免视看| 91精品国产乱码久久| 国产精品久久久久影院亚瑟| 日韩av片网站| 久久亚洲国产| 成人精品aaaa网站| av文字幕在线观看| 欧美一区二区视频在线观看| 国产第一页浮力| 国产v日产∨综合v精品视频| 粉嫩av一区二区三区天美传媒| 免费观看亚洲天堂| 欧美黑人极品猛少妇色xxxxx| 亚洲xxx在线| 亚洲国产一区在线观看| 久久久久成人精品无码中文字幕| 在线视频日韩| 欧美一区二区三区在线播放| 综合在线影院| 中文日韩电影网站| 国产美女免费看| 亚洲一二三四在线| 91av视频在线观看| 农村末发育av片一区二区| 中文字幕乱码亚洲无线精品一区| 99国产视频| 国产网站在线| 亚洲人成电影网| 亚洲综合精品视频| 一区二区不卡在线视频 午夜欧美不卡在| 成人在线短视频| 夜久久久久久| 午夜精品一区二区三区在线观看| 青青久久精品| youjizz亚洲| 色天天综合色天天久久| aa片在线观看视频在线播放| 国产精品人人爽人人做我的可爱| 精品日本一区二区三区在线观看| 成人美女大片| 在线视频欧美日韩精品| 国产aⅴ爽av久久久久成人| 亚洲国产一区视频| 无码 人妻 在线 视频| 激情久久五月天| 日韩伦理在线免费观看| 欧美一区二区三区高清视频| 国产在线观看精品一区二区三区| 污污片在线免费视频| 亚洲女同精品视频| 国产黄a三级三级三级| 欧美日韩在线第一页| 网爆门在线观看| 国产成人亚洲精品狼色在线 | 久久久久久无码精品人妻一区二区| 伊人久久久大香线蕉综合直播| 日韩欧美在线观看强乱免费| 日韩视频一二区| 色综合天天狠狠| 91大神福利视频| 成人精品国产免费网站| 日韩一级片播放| 欧美精品国产| 亚洲高清视频一区二区| 99ri日韩精品视频| 国产欧美久久一区二区| 手机在线理论片| 欧美成年人视频| 国产日韩精品在线看| 精品久久久久久久久久久久久久久 | 91亚洲国产成人精品性色| 欧美a级在线观看| 久久综合亚洲社区| 91福利在线视频| 亚洲精品国产综合区久久久久久久| 国产一区二区三区三州| 色婷婷av一区二区三区之一色屋| 99re在线播放| 久久精品女人天堂av免费观看 | 天天操天天摸天天舔| www.欧美色图| 蜜桃视频无码区在线观看| 97超碰国产一区二区三区| 欧美精品丝袜久久久中文字幕| 影音先锋亚洲天堂| 亚洲综合在线视频| www.99re6| 欧美激情一区二区三区全黄| 鲁大师私人影院在线观看| 国产成人精品综合在线观看| 国产精品嫩草影院8vv8 | 午夜精品123| 免费看一级一片| 亚洲激情一二三区| 动漫性做爰视频| 亚洲人成小说网站色在线| 在线观看天堂av| 国产精品麻豆欧美日韩ww| 免费一级做a爰片久久毛片潮| 91视视频在线观看入口直接观看www | 欧美精品久久久久性色| 亚洲欧美电影一区二区| 久久国产波多野结衣| 中文字幕一区视频| 亚洲欧美卡通动漫| 自拍视频在线观看一区二区| 亚洲综合第一区| 国产精品久久777777| 精品丰满少妇一区二区三区| 国产精品短视频| 亚洲av无一区二区三区| 国产精品女主播在线观看| 美女av免费看| 国产精品白丝在线| 一区二区国产精品精华液| 国产精品夫妻自拍| 久草视频免费在线播放| 亚洲香蕉伊在人在线观| 日韩男人的天堂| 一本一道波多野结衣一区二区| 成人午夜精品视频| 91精品国产综合久久久久久漫画 | 女人床在线观看| 亚洲毛片网站| 日韩精品一区中文字幕| 麻豆精品国产91久久久久久| √天堂资源在线| 成人激情av网| 伊人网伊人影院| 亚洲欧美在线另类| 国产无码精品在线观看| 色综合中文字幕国产| 国模私拍一区二区| 精品少妇一区二区三区免费观看 | 久久综合九色综合欧美就去吻| 蜜臀久久99精品久久久久久| 国产精品久久久久久久蜜臀| 亚洲av无码一区二区三区在线| 亚洲成a人片综合在线| 久久久蜜桃一区二区| 6080国产精品一区二区| 少妇人妻精品一区二区三区| 夜夜嗨av一区二区三区四区| 国产美女在线观看| 欧美一区二区三区精品电影| 四虎影视成人精品国库在线观看| 动漫3d精品一区二区三区 | 最近中文字幕日韩精品| 国语对白在线刺激| 国产精品一区二区三区免费视频 | 一本一本a久久| 亚洲区欧美区| 日韩在线不卡一区| 99精品欧美一区二区蜜桃免费| 制服丨自拍丨欧美丨动漫丨| 亚洲第一在线综合网站| 中文字幕在线观看免费| 亚洲国产精品小视频| 免费在线观看黄色网| 欧洲成人性视频| 88久久精品| 亚洲一区二三| 亚欧成人精品| 国产精品嫩草69影院| 国产精品美女久久久久aⅴ国产馆 国产精品美女久久久久av爽李琼 国产精品美女久久久久高潮 | 可以在线看的av网站| 另类的小说在线视频另类成人小视频在线 | 美女福利视频一区| 欧洲精品一区二区三区| 国产精品免费一区二区三区四区| 日韩欧美在线中字| av动漫在线观看| www.成人网.com| 妺妺窝人体色www聚色窝仙踪| 欧美日本乱大交xxxxx| 欧美日韩国产综合视频| 久久久免费精品视频| 久久69av| 久久久国产精华液999999| 蜜臀av一区二区| av黄色在线免费观看| 欧美日韩国产一中文字不卡| 亚洲xxx在线| 久久99精品视频一区97| 祥仔av免费一区二区三区四区| 日韩欧美亚洲v片| 日韩专区欧美专区| 37p粉嫩大胆色噜噜噜| 五月天精品一区二区三区| 亚洲精品911| 欧美高清视频免费观看| 秋霞影院一区| 人妻激情另类乱人伦人妻| 国产麻豆精品在线| 91视频免费在线看| 欧美一区二区日韩一区二区| 免费av在线网址| 亚洲一区二区三区久久| 91成人超碰| 国产黄色一区二区三区| 亚洲免费观看高清完整版在线观看 | 国产成人8x视频一区二区| 中文字幕亚洲欧美日韩| 欧美一区二区三区播放老司机| av大全在线| 成人欧美一区二区三区视频 | 日本高清不卡的在线| 羞羞答答一区二区| 777米奇影视第四色| 国产无一区二区| 亚洲熟妇无码久久精品| 色诱女教师一区二区三区| 日本a人精品| 在线观看17c| 成人一道本在线| 亚洲视频免费播放| 亚洲色图综合网| 亚洲二区av| 日本a在线天堂| www.av亚洲| 最新在线中文字幕| 久久精品2019中文字幕| 我要色综合中文字幕| 奇米精品一区二区三区| 国产亚洲综合在线| 国产原创中文av| 久久久久久久久久国产| 西瓜成人精品人成网站| 天天操天天爽天天射| 亚洲男帅同性gay1069| 天堂网在线中文| 国产精品激情av电影在线观看 | 欧美成人免费播放| 日韩影视高清在线观看| 亚州精品一二三区| 亚洲精品水蜜桃| 欧美巨乳在线| 91老司机精品视频| 亚洲乱码久久| 永久免费看mv网站入口| 欧美精品一区二区三区蜜臀| 成人影院av| 中文字幕在线乱| 91免费视频网| 国产视频aaa| 欧美在线xxx| www在线观看播放免费视频日本| 日韩毛片精品高清免费| 国产xxxxxx| 国产成人午夜视频网址 | 99在线精品免费视频| 欧美激情一区二区在线| 秋霞av鲁丝片一区二区| 国产精品亚发布| 国产毛片久久| 妺妺窝人体色www在线下载| 一区二区在线免费视频| 成人h动漫免费观看网站| 国产一级做a爰片久久|