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

JVM深度剖析:一文詳解JVM是如何實現反射的?

云計算 虛擬化
反射是 Java 語言中一個相當重要的特性,它允許正在運行的 Java 程序觀測,甚至是修改程序的動態行為。

 [[422686]]

反射是 Java 語言中一個相當重要的特性,它允許正在運行的 Java 程序觀測,甚至是修改程序的動態行為。

舉例來說,我們可以通過 Class 對象枚舉該類中的所有方法,我們還可以通過Method.setAccessible(位于 java.lang.reflect 包,該方法繼承自 AccessibleObject)繞過 Java 語言的訪問權限,在私有方法所在類之外的地方調用該方法。

反射在 Java 中的應用十分廣泛。開發人員日常接觸到的 Java 集成開發環境(IDE)便運用了這一功能:每當我們敲入點號時,IDE 便會根據點號前的內容,動態展示可以訪問的字段或者方法。

另一個日常應用則是 Java 調試器,它能夠在調試過程中枚舉某一對象所有字段的值。

(圖中 eclipse 的自動提示使用了反射)

在 Web 開發中,我們經常能夠接觸到各種可配置的通用框架。為了保證框架的可擴展性,它們往往借助 Java 的反射機制,根據配置文件來加載不同的類。舉例來說,Spring 框架的依賴反轉(IoC),便是依賴于反射機制。

然而,我相信不少開發人員都嫌棄反射機制比較慢。甚至是甲骨文關于反射的教學網頁[1],也強調了反射性能開銷大的缺點。

反射調用的實現

首先,我們來看看方法的反射調用,也就是 Method.invoke,是怎么實現的。

  1. public final class Method extends Executable { 
  2.     ... 
  3.     public Object invoke(Object obj, Object... args) throws ... { 
  4.         ... //權限檢查 
  5.         MethodAccessor ma = methodAccessor; 
  6.         if (ma == null) { 
  7.             ma = acquireMethodAccessor(); 
  8.         } 
  9.         return ma.invoke(obj, args); 
  10.     } 

如果你查閱 Method.invoke 的源代碼,那么你會發現,它實際上委派給MethodAccessor 來處理。MethodAccessor 是一個接口,它有兩個已有的具體實現:一個通過本地方法來實現反射調用,另一個則使用了委派模式。為了方便記憶,我便用“本地實現”和“委派實現”來指代這兩者。

每個 Method 實例的第一次反射調用都會生成一個委派實現,它所委派的具體實現便是一個本地實現。本地實現非常容易理解。當進入了 Java 虛擬機內部之后,我們便擁有了Method 實例所指向方法的具體地址。這時候,反射調用無非就是將傳入的參數準備好,然后調用進入目標方法。

  1. // v0版本 
  2. import java.lang.reflect.Method; 
  3. public class Test { 
  4.     public static void target(int i) { 
  5.         new Exception("#" + i).printStackTrace(); 
  6.     } 
  7.     public static void main(String[] args) throws Exception { 
  8.         Class<?> klass = Class.forName("Test"); 
  9.         Method method = klass.getMethod("target"int.class); 
  10.         method.invoke(null, 0); 
  11.     } 
  12. #不同版本的輸出略有不同,這里我使用了Java 10。 
  13. $ java Test 
  14. java.lang.Exception: #0 
  15. at Test.target(Test.java:5) 
  16. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl .invoke0(Native Methoa      t java.base/jdk.internal.reflect.NativeMethodAccessorImpl. .invoke(NativeMethodAt       java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.i .invoke(Delegatin 
  17. java.base/java.lang.reflect.Method.invoke(Method.java:564) 
  18. t        Test.main(Test.java:131 

為了方便理解,我們可以打印一下反射調用到目標方法時的棧軌跡。在上面的 v0 版本代碼中,我們獲取了一個指向 Test.target 方法的 Method 對象,并且用它來進行反射調用。在 Test.target 中,我會打印出棧軌跡。

可以看到,反射調用先是調用了 Method.invoke,然后進入委派實現(DelegatingMethodAccessorImpl),再然后進入本地實現(NativeMethodAccessorImpl),最后到達目標方法。

這里你可能會疑問,為什么反射調用還要采取委派實現作為中間層?直接交給本地實現不可以么?

其實,Java 的反射調用機制還設立了另一種動態生成字節碼的實現(下稱動態實現),直接使用 invoke 指令來調用目標方法。之所以采用委派實現,便是為了能夠在本地實現以及動態實現中切換。

  1. //動態實現的偽代碼,這里只列舉了關鍵的調用邏輯,其實它還包括調用者檢測、參數檢測的字節碼。 
  2. package jdk.internal.reflect; 
  3. public class GeneratedMethodAccessor1 extends ... { 
  4.     @Overrides 
  5.     public Object invoke(Object obj, Object[] args) throws ... { 
  6.         Test.target((int) args[0]); 
  7.         return null
  8.     } 

動態實現和本地實現相比,其運行效率要快上 20 倍。這是因為動態實現無需經過 Java到 C++ 再到 Java 的切換,但由于生成字節碼十分耗時,僅調用一次的話,反而是本地實現要快上 3 到 4 倍。

考慮到許多反射調用僅會執行一次,Java 虛擬機設置了一個閾值 15(可以通過-Dsun.reflect.inflationThreshold= 來調整),當某個反射調用的調用次數在 15 之下時,采用本地實現;當達到 15 時,便開始動態生成字節碼,并將委派實現的委派對象切換至動態實現,這個過程我們稱之為 Inflation。

為了觀察這個過程,我將剛才的例子更改為下面的 v1 版本。它會將反射調用循環 20 次。

  1. // v1版本 
  2. import java.lang.reflect.Method; 
  3. public class Test { 
  4.     public static void target(int i) { 
  5.         new Exception("#" + i).printStackTrace(); 
  6.     } 
  7.     public static void main(String[] args) throws Exception { 
  8.         Class<?> klass = Class.forName("Test"); 
  9.         Method method = klass.getMethod("target"int.class); 
  10.         for (int i = 0; i < 20; i++) { 
  11.             method.invoke(null, i); 
  12.         } 
  13.     } 
  14. #使用-verbose:class打印加載的類 
  15. $ java -verbose:class Test 
  16. ... 
  17. java.lang.Exception: #14 
  18. at Test.target(Test.java:5) 
  19. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl .invoke0(Native Methoat java.base/jdk.internal.reflect.NativeMethodAccessorImpl .invoke(NativeMethodAat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl .invoke(Delegatinat java.base/java.lang.reflect.Method.invoke(Method.java:564) 
  20. at Test.main(Test.java:12) 
  21. [0.158s][info][class,load] ... 
  22. ... 
  23. [0.160s][info][class,load] jdk.internal.reflect.GeneratedMethodAccessor1 source: __JVM_Djava.lang.Exception: #15 
  24. at Test.target(Test.java:5) 
  25. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl .invoke0(Native Methodat java.base/jdk.internal.reflect.NativeMethodAccessorImpl .invoke(NativeMethodAcat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl .invoke(Delegatingat java.base/java.lang.reflect.Method.invoke(Method.java:564) 
  26. at Test.main(Test.java:12) 
  27. java.lang.Exception: #16 
  28. at Test.target(Test.java:5) 
  29. at jdk.internal.reflect.GeneratedMethodAccessor1 .invoke(Unknown Source) 
  30. at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl .invoke(Delegatingat java.base/java.lang.reflect.Method.invoke(Method.java:564) 
  31. at Test.main(Test.java:12) 
  32. ... 

可以看到,在第 15 次(從 0 開始數)反射調用時,我們便觸發了動態實現的生成。這時候,Java 虛擬機額外加載了不少類。其中,最重要的當屬GeneratedMethodAccessor1(第 30 行)。并且,從第 16 次反射調用開始,我們便切換至這個剛剛生成的動態實現(第 40 行)。

反射調用的 Inflation 機制是可以通過參數(-Dsun.reflect.noInflation=true)來關閉的。這樣一來,在反射調用一開始便會直接生成動態實現,而不會使用委派實現或者本地實現。

反射調用的開銷

下面,我們便來拆解反射調用的性能開銷。

在剛才的例子中,我們先后進行了 Class.forName,Class.getMethod 以及Method.invoke 三個操作。其中,Class.forName 會調用本地方法,Class.getMethod則會遍歷該類的公有方法。如果沒有匹配到,它還將遍歷父類的公有方法。可想而知,這兩個操作都非常費時。

值得注意的是,以 getMethod 為代表的查找方法操作,會返回查找得到結果的一份拷貝。因此,我們應當避免在熱點代碼中使用返回 Method 數組的 getMethods 或者getDeclaredMethods 方法,以減少不必要的堆空間消耗。

在實踐中,我們往往會在應用程序中緩存 Class.forName 和 Class.getMethod 的結果。因此,下面我就只關注反射調用本身的性能開銷。

為了比較直接調用和反射調用的性能差距,我將前面的例子改為下面的 v2 版本。它會將反射調用循環二十億次。此外,它還將記錄下每跑一億次的時間。

我將取最后五個記錄的平均值,作為預熱后的峰值性能。(注:這種性能評估方式并不嚴謹,我會在專欄的第三部分介紹如何用 JMH 來測性能。)

在我這個老筆記本上,一億次直接調用耗費的時間大約在 120ms。這和不調用的時間是一致的。其原因在于這段代碼屬于熱循環,同樣會觸發即時編譯。并且,即時編譯會將對Test.target 的調用內聯進來,從而消除了調用的開銷。

  1. // v2版本 
  2. mport java.lang.reflect.Method; 
  3. public class Test { 
  4.     public static void target(int i) { 
  5.         //空方法 
  6.     } 
  7.     public static void main(String[] args) throws Exception { 
  8.         Class<?> klass = Class.forName("Test"); 
  9.         Method method = klass.getMethod("target"int.class); 
  10.         long current = System.currentTimeMillis(); 
  11.         for (int i = 1; i <= 2_000_000_000; i++) { 
  12.             if (i % 100_000_000 == 0) { 
  13.                 long temp = System.currentTimeMillis(); 
  14.                 System.out.println(temp - current); 
  15.                 current = temp
  16.             } 
  17.             method.invoke(null, 128); 
  18.         } 
  19.     } 

下面我將以 120ms 作為基準,來比較反射調用的性能開銷。

由于目標方法 Test.target 接收一個 int 類型的參數,因此我傳入 128 作為反射調用的參數,測得的結果約為基準的 2.7 倍。我們暫且不管這個數字是高是低,先來看看在反射調用之前字節碼都做了什么。

  1. aload_2                         //加載Method對象 
  2. aconst_null                     //反射調用的第一個參數null 
  3. iconst_1 
  4. anewarray Object                //生成一個長度為1的Object數組 
  5. dup 
  6. iconst_0 
  7. sipush 128 
  8. invokestatic Integer.valueOf    //將128自動裝箱成Integer73: aastore                         //存入Object數組中 
  9. invokevirtual Method.invoke     //反射調用 

這里我截取了循環中反射調用編譯而成的字節碼。可以看到,這段字節碼除了反射調用外,還額外做了兩個操作。

  • 由于 Method.invoke 是一個變長參數方法,在字節碼層面它的最后一個參數會是Object 數組(感興趣的同學私下可以用 javap 查看)。Java 編譯器會在方法調用處生成一個長度為傳入參數數量的 Object 數組,并將傳入參數一一存儲進該數組中。
  • 由于 Object 數組不能存儲基本類型,Java 編譯器會對傳入的基本類型參數進行自動裝箱。

這兩個操作除了帶來性能開銷外,還可能占用堆內存,使得 GC 更加頻繁。(如果你感興趣的話,可以用虛擬機參數 -XX:+PrintGC 試試。)那么,如何消除這部分開銷呢?

關于第二個自動裝箱,Java 緩存了 [-128, 127] 中所有整數所對應的 Integer 對象。當需要自動裝箱的整數在這個范圍之內時,便返回緩存的 Integer,否則需要新建一個 Integer對象。

因此,我們可以將這個緩存的范圍擴大至覆蓋 128(對應參數-Djava.lang.Integer.IntegerCache.high=128),便可以避免需要新建 Integer 對象的場景。

或者,我們可以在循環外緩存 128 自動裝箱得到的 Integer 對象,并且直接傳入反射調用中。這兩種方法測得的結果差不多,約為基準的 1.8 倍。

現在我們再回來看看第一個因變長參數而自動生成的 Object 數組。既然每個反射調用對應的參數個數是固定的,那么我們可以選擇在循環外新建一個 Object 數組,設置好參數,并直接交給反射調用。改好的代碼可以參照文稿中的 v3 版本。

  1. // v3版本 
  2. import java.lang.reflect.Method; 
  3. public class Test { 
  4.     public static void target(int i) { 
  5.         //空方法 
  6.     } 
  7.     public static void main(String[] args) throws Exception { 
  8.         Class<?> klass = Class.forName("Test"); 
  9.         Method method = klass.getMethod("target"int.class); 
  10.         Object[] arg = new Object[1]; 
  11.         //在循環外構造參數數組 
  12.         arg[0] = 128; 
  13.         long current = System.currentTimeMillis(); 
  14.         for (int i = 1; i <= 2_000_000_000; i++) { 
  15.             if (i % 100_000_000 == 0) { 
  16.                 long temp = System.currentTimeMillis(); 
  17.                 System.out.println(temp - current); 
  18.                 current = temp
  19.             } 
  20.             method.invoke(null, arg); 
  21.         } 
  22.     } 

測得的結果反而更糟糕了,為基準的 2.9 倍。這是為什么呢?

如果你在上一步解決了自動裝箱之后查看運行時的 GC 狀況,你會發現這段程序并不會觸發 GC。其原因在于,原本的反射調用被內聯了,從而使得即時編譯器中的逃逸分析將原本新建的 Object 數組判定為不逃逸的對象。

如果一個對象不逃逸,那么即時編譯器可以選擇棧分配甚至是虛擬分配,也就是不占用堆空間。具體我會在本專欄的第二部分詳細解釋。

如果在循環外新建數組,即時編譯器無法確定這個數組會不會中途被更改,因此無法優化掉訪問數組的操作,可謂是得不償失。

到目前為止,我們的最好記錄是 1.8 倍。那能不能再進一步提升呢?

剛才我曾提到,可以關閉反射調用的 Inflation 機制,從而取消委派實現,并且直接使用動態實現。此外,每次反射調用都會檢查目標方法的權限,而這個檢查同樣可以在 Java 代碼里關閉,在關閉了這兩項機制之后,也就得到了我們的 v4 版本,它測得的結果約為基準的1.3 倍。

  1. // v4版本 
  2. import java.lang.reflect.Method; 
  3. //在運行指令中添加如下兩個虛擬機參數: 
  4. // -Djava.lang.Integer.IntegerCache.high=128 
  5. // -Dsun.reflect.noInflation=true 
  6. public class Test { 
  7.     public static void target(int i) { 
  8.         //空方法 
  9.     } 
  10.     public static void main(String[] args) throws Exception { 
  11.         Class<?> klass = Class.forName("Test"); 
  12.         Method method = klass.getMethod("target"int.class); 
  13.         method.setAccessible(true); 
  14.         //關閉權限檢查 
  15.         long current = System.currentTimeMillis(); 
  16.         for (int i = 1; i <= 2_000_000_000; i++) { 
  17.             if (i % 100_000_000 == 0) { 
  18.                 long temp = System.currentTimeMillis(); 
  19.                 System.out.println(temp - current); 
  20.                 current = temp
  21.             } 
  22.             method.invoke(null, 128); 
  23.         } 
  24.     } 

到這里,我們基本上把反射調用的水分都榨干了。接下來,我來把反射調用的性能開銷給提回去。

首先,在這個例子中,之所以反射調用能夠變得這么快,主要是因為即時編譯器中的方法內聯。在關閉了 Inflation 的情況下,內聯的瓶頸在于 Method.invoke 方法中對MethodAccessor.invoke 方法的調用。

我會在后面的文章中介紹方法內聯的具體實現,這里先說個結論:在生產環境中,我們往往擁有多個不同的反射調用,對應多個 GeneratedMethodAccessor,也就是動態實現。

由于 Java 虛擬機的關于上述調用點的類型 profile(注:對于 invokevirtual 或者invokeinterface,Java 虛擬機會記錄下調用者的具體類型,我們稱之為類型 profile)無法同時記錄這么多個類,因此可能造成所測試的反射調用沒有被內聯的情況。

  1. // v5版本 
  2. import java.lang.reflect.Method; 
  3. public class Test { 
  4.     public static void target(int i) { 
  5.         //空方法 
  6.     } 
  7.     public static void main(String[] args) throws Exception { 
  8.         Class<?> klass = Class.forName("Test"); 
  9.         Method method = klass.getMethod("target"int.class); 
  10.         method.setAccessible(true); 
  11.         //關閉權限檢查 
  12.         polluteProfile(); 
  13.         long current = System.currentTimeMillis(); 
  14.         for (int i = 1; i <= 2_000_000_000; i++) { 
  15.             if (i % 100_000_000 == 0) { 
  16.                 long temp = System.currentTimeMillis(); 
  17.                 System.out.println(temp - current); 
  18.                 current = temp
  19.             } 
  20.             method.invoke(null, 128); 
  21.         } 
  22.     } 
  23.     public static void polluteProfile() throws Exception { 
  24.         Method method1 = Test.class.getMethod("target1"int.class); 
  25.         Method method2 = Test.class.getMethod("target2"int.class); 
  26.         for (int i = 0; i < 2000; i++) { 
  27.             method1.invoke(null, 0); 
  28.             method2.invoke(null, 0); 
  29.         } 
  30.     } 
  31.     public static void target1(int i) { 
  32.     } 
  33.     public static void target2(int i) { 
  34.     } 

在上面的 v5 版本中,我在測試循環之前調用了 polluteProfile 的方法。該方法將反射調用另外兩個方法,并且循環上 2000 遍。

而測試循環則保持不變。測得的結果約為基準的 6.7 倍。也就是說,只要誤擾了Method.invoke 方法的類型 profile,性能開銷便會從 1.3 倍上升至 6.7 倍。

之所以這么慢,除了沒有內聯之外,另外一個原因是逃逸分析不再起效。這時候,我們便可以采用剛才 v3 版本中的解決方案,在循環外構造參數數組,并直接傳遞給反射調用。這樣子測得的結果約為基準的 5.2 倍。

除此之外,我們還可以提高 Java 虛擬機關于每個調用能夠記錄的類型數目(對應虛擬機參數 -XX:TypeProfileWidth,默認值為 2,這里設置為 3)。最終測得的結果約為基準的2.8 倍,盡管它和原本的 1.3 倍還有一定的差距,但總算是比 6.7 倍好多了。

總結與實踐

在默認情況下,方法的反射調用為委派實現,委派給本地實現來進行方法調用。在調用超過15 次之后,委派實現便會將委派對象切換至動態實現。這個動態實現的字節碼是自動生成的,它將直接使用 invoke 指令來調用目標方法。

方法的反射調用會帶來不少性能開銷,原因主要有三個:變長參數方法導致的 Object 數組,基本類型的自動裝箱、拆箱,還有最重要的方法內聯。

本文的實踐環節,你可以將最后一段代碼中 polluteProfile 方法的兩個 Method 對象,都改成獲取名字為“target”的方法。請問這兩個獲得的 Method 對象是同一個嗎(==)?他們 equal 嗎(.equals(…))?對我們的運行結果有什么影響?

  1. import java.lang.reflect.Method; 
  2. public class Test { 
  3.     public static void target(int i) { 
  4.         //空方法 
  5.     } 
  6.     public static void main(String[] args) throws Exception { 
  7.         Class<?> klass = Class.forName("Test"); 
  8.         Method method = klass.getMethod("target"int.class); 
  9.         method.setAccessible(true); 
  10.         //關閉權限檢查 
  11.         polluteProfile(); 
  12.         long current = System.currentTimeMillis(); 
  13.         for (int i = 1; i <= 2_000_000_000; i++) { 
  14.             if (i % 100_000_000 == 0) { 
  15.                 long temp = System.currentTimeMillis(); 
  16.                 System.out.println(temp - current); 
  17.                 current = temp
  18.             } 
  19.             method.invoke(null, 128); 
  20.         } 
  21.     } 
  22.     public static void polluteProfile() throws Exception { 
  23.         Method method1 = Test.class.getMethod("target"int.class); 
  24.         Method method2 = Test.class.getMethod("target"int.class); 
  25.         for (int i = 0; i < 2000; i++) { 
  26.             method1.invoke(null, 0); 
  27.             method2.invoke(null, 0); 
  28.         } 
  29.     } 
  30.     public static void target1(int i) { 
  31.     } 
  32.     public static void target2(int i) { 
  33.     } 

 

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2019-10-11 08:41:35

JVM虛擬機語言

2020-01-07 14:43:26

JVM類加載器執行引擎

2021-10-13 21:43:18

JVMRPC框架

2021-06-06 13:06:34

JVM內存分布

2023-10-07 08:41:42

JavaJVM

2024-08-26 08:58:50

2023-08-27 21:29:43

JVMFullGC調優

2021-09-08 17:42:45

JVM內存模型

2021-01-27 11:10:49

JVM性能調優

2010-09-26 14:32:34

JDKJREJVM

2020-05-20 22:28:10

JVM運行機制

2021-08-11 10:21:24

云直播阿里云邊緣云

2018-08-16 08:19:30

2025-01-13 12:00:00

反射Java開發

2025-04-27 09:59:38

深度學習AI人工智能

2019-12-12 11:19:33

JVM內存線程

2022-05-26 15:44:43

混合網絡網絡安全

2021-08-06 09:21:26

Linux內核 Coredump

2019-10-28 10:19:27

JVM 類加載器Java

2021-08-09 16:39:52

工具JVM剖析
點贊
收藏

51CTO技術棧公眾號

久久99国内| 四虎av在线| 蜜桃视频免费观看一区| 久久中文字幕一区| 亚洲一区二区三区四区av| 粉嫩一区二区| 亚洲女同ⅹxx女同tv| 久久涩涩网站| a天堂在线观看视频| 美女视频一区免费观看| 久久九九国产精品怡红院 | 一炮成瘾1v1高h| 影音先锋久久久| 这里精品视频免费| 男男一级淫片免费播放| 六九午夜精品视频| 疯狂蹂躏欧美一区二区精品| 一本色道久久综合亚洲精品婷婷| 黄色一级a毛片| 久久电影网电视剧免费观看| 55夜色66夜色国产精品视频| 欧美黑人猛猛猛| 成人在线国产| 精品小视频在线| 黑人玩弄人妻一区二区三区| 精品久久久网| 色噜噜狠狠成人中文综合| 激情五月婷婷六月| 国产区在线看| 国产精品久久久久久亚洲伦| 美国av一区二区三区| 亚洲AV无码精品国产| 久久精品国产999大香线蕉| 57pao成人国产永久免费| 福利所第一导航| 性欧美欧美巨大69| 在线看福利67194| 伊人网伊人影院| 婷婷综合电影| 日韩经典第一页| 少妇精品无码一区二区三区| 色播一区二区| 欧美一区二区三区日韩| 五月天婷婷亚洲| 日韩电影精品| 欧美日韩精品一区二区三区四区| 日本成年人网址| 欧美sm一区| 懂色av一区二区三区| 日韩小视频在线播放| h片视频在线观看| 亚洲主播在线观看| 免费一级淫片aaa片毛片a级| 污影院在线观看| 亚洲午夜久久久久久久久电影院| 日韩精品手机在线观看| 日韩电影免费观看| 亚洲成人免费在线观看| 欧美人成在线观看| 国产伦久视频在线观看| 天天av天天翘天天综合网| 福利视频一区二区三区四区| 黄色在线观看www| 欧美午夜激情视频| 日韩av一二三四| 国产亚洲欧美日韩精品一区二区三区| 欧美三级欧美一级| 午夜久久福利视频| 欧美国产亚洲精品| 精品国产凹凸成av人网站| 国产情侣久久久久aⅴ免费| 韩国精品福利一区二区三区| 亚洲国产一区自拍| 91网站免费视频| 国产韩日影视精品| 欧美夫妻性视频| 日本一级一片免费视频| 葵司免费一区二区三区四区五区| 国产精品福利无圣光在线一区| 伊人网站在线观看| 国产盗摄一区二区三区| 激情一区二区三区| 91欧美在线视频| 一区二区三区四区精品在线视频| 成人免费播放器| 日本.亚洲电影| 欧美一区二区三区影视| 日本不卡视频一区| 国语产色综合| 久久成人免费视频| 日韩精品1区2区| 捆绑调教一区二区三区| 成人欧美一区二区三区黑人免费| 日韩私人影院| 亚洲色图丝袜美腿| www.中文字幕在线| 精品亚洲a∨| 亚洲国产高潮在线观看| 18精品爽国产三级网站| 亚洲美女少妇无套啪啪呻吟| 国产精品亚洲综合天堂夜夜| 高h调教冰块play男男双性文| 久久亚洲精精品中文字幕早川悠里 | 亚洲靠逼com| 亚洲国产精品久久久久婷蜜芽| 国产精成人品2018| 亚洲成人三级在线| 182在线观看视频| 久久久精品五月天| 都市激情久久久久久久久久久| 激情综合闲人网| 亚洲一级二级在线| 国产无色aaa| 红桃成人av在线播放| 欧美激情在线观看视频| 波多野结衣视频观看| 成人国产精品视频| 特级黄色录像片| 精品成人免费一区二区在线播放| 欧美精品一区二区在线观看| caoporn91| 久久99精品久久久久久国产越南 | 国产欧美最新羞羞视频在线观看| 少妇精品高潮欲妇又嫩中文字幕| 亚洲三级在线免费| 中文字幕网av| 精品99久久| 97精品久久久| 蜜臀久久99精品久久久| 亚洲欧洲综合另类在线| 免费一区二区三区在线观看| 美女少妇全过程你懂的久久| 8x海外华人永久免费日韩内陆视频| 精品国产无码一区二区| 亚洲男人的天堂av| 国产乱码一区二区三区四区| 欧美美女在线| 国产成人福利网站| 蜜桃视频在线观看视频| 日韩欧美在线免费观看| 亚洲精品女人久久久| 亚洲一级一区| 国产另类第一区| www欧美xxxx| 欧美精品一区二区三区在线播放| 欧美精品乱码视频一二专区| 国产乱理伦片在线观看夜一区| 黄色高清视频网站| 国产一区二区三区亚洲综合| 两个人的视频www国产精品| 国产精品久久久久久在线| 亚洲欧洲精品一区二区三区不卡| 天天干天天色天天干| 午夜精品一区二区三区国产| 亚洲一区二区三区sesese| 国产黄色在线免费观看| 日韩一区二区麻豆国产| 免费又黄又爽又色的视频| 粉嫩欧美一区二区三区高清影视 | wwwwxxxx在线观看| 日韩黄色在线免费观看| 久久久久久亚洲av无码专区| 中文一区二区在线观看| www.99r| 国产一区亚洲| 国外成人在线视频网站| 亚洲男人av| 丝袜情趣国产精品| 99久久久无码国产精品免费| 亚洲午夜电影在线| 深爱五月激情网| 蜜臀久久99精品久久久画质超高清| 亚洲一区二区高清视频| 亚洲国产高清在线观看| 91av在线免费观看视频| 高清福利在线观看| 69堂成人精品免费视频| 国产一级在线观看视频| 久久久精品国产免费观看同学| 国产一级做a爰片久久| 欧美成人首页| 久久久久久九九九九| 99riav视频一区二区| 欧美情侣性视频| 日本又骚又刺激的视频在线观看| 在线观看亚洲精品| 欧美成人精品欧美一级私黄| 不卡的看片网站| 久久综合伊人77777麻豆最新章节| 久久人人88| 国产在线一区二区三区四区 | 一区二区三区福利| 亚洲国产精品一区在线观看不卡 | 三妻四妾的电影电视剧在线观看| 在线观看欧美视频| 亚洲免费黄色片| 欧美午夜片在线观看| 免费一级a毛片夜夜看| 久久精品免视看| 久久久精品人妻一区二区三区| 国产精品最新自拍| 成年人三级视频| 免费一区二区三区视频导航| 成人激情直播| 精品亚洲a∨| 国产91精品久| 欧美bbbxxxxx| 大胆欧美人体视频| 九九在线视频| 亚洲国产成人久久综合一区| 国产片在线播放| 精品视频一区 二区 三区| 亚洲一区 视频| 亚洲精选一二三| 99久久精品久久亚洲精品| 国产一区二区三区高清在线观看| 日本手机在线视频| 国产一区二区三区探花| av一区二区在线看| 四虎影视国产精品| 欧洲精品久久久| 久草免费在线色站| 久久影视电视剧免费网站清宫辞电视 | 黄av在线免费观看| 亚洲人成电影网站色| 亚洲男人天堂久久| 日韩欧美在线不卡| 一级aaaa毛片| 色菇凉天天综合网| 97久久久久久久| 亚洲制服丝袜一区| 欧美日韩在线视频免费播放| 国产精品嫩草久久久久| 我和岳m愉情xxxⅹ视频| 波多野结衣中文字幕一区二区三区 | 精品无码m3u8在线观看| 日韩一区欧美小说| 国产在线观看免费视频软件| 国产精品久久一卡二卡| 调教驯服丰满美艳麻麻在线视频| 91免费国产在线| 最新在线黄色网址| 99v久久综合狠狠综合久久| 国产原创剧情av| 成人av在线电影| 蜜臀aⅴ国产精品久久久国产老师| 欧美96一区二区免费视频| 嫩草影院国产精品| 美女看a上一区| 一道本在线免费视频| 精品一区二区在线免费观看| 婷婷激情5月天| 国产精品中文字幕日韩精品| 能看毛片的网站| 国产在线精品一区二区三区不卡| 国产精品igao网网址不卡| 国产成人免费视频精品含羞草妖精| 欧美专区第二页| 成人黄色综合网站| 亚洲av无码一区二区三区网址| 97se亚洲国产综合自在线| 欧美肥妇毛茸茸| 中文字幕一级片| 911精品国产一区二区在线| 国产精品久久久国产盗摄| 日韩亚洲欧美一区| 人妻一区二区三区免费| 亚洲美女在线视频| www免费网站在线观看| 神马久久久久久| 亚洲色图欧美另类| 亚洲s色大片| 日韩中文字幕视频| 污片在线免费观看| 国内偷自视频区视频综合 | 欧美亚洲日本网站| 日本欧美一区| 91精品国产91久久久久青草| 欧美午夜寂寞| 杨幂一区欧美专区| 亚洲成人中文| 一区二区三区免费播放| 国产成人精品免费| 久久亚洲AV成人无码国产野外 | 欧美视频在线视频精品| julia一区二区中文久久94| 亚洲精品456| 在线观看欧美亚洲| 一区二区三区国产在线| 国产精品v日韩精品v在线观看| 国产白丝精品91爽爽久久| 久久精品老司机| 一区二区欧美精品| 国产性生活视频| 日韩欧美123| 黄色电影免费在线看| 久99久在线视频| 精品成人免费一区二区在线播放| 国产精品国模大尺度私拍| 日韩欧美字幕| 男人的天堂99| 国产91精品免费| 色撸撸在线视频| 欧美日韩中文在线观看| www.污视频| 最新亚洲国产精品| 97成人资源| 国产经典一区二区三区| 99热精品久久| 成人在线观看黄| 99精品久久久久久| 亚洲国产精品免费在线观看| 在线国产电影不卡| 亚洲欧美日韩综合在线| 欧美成人一区二区三区电影| 成人国产精品一区二区免费麻豆| 国产视频精品网| 欧美久久九九| 午夜天堂在线视频| 国产精品私人自拍| 一级做a爰片久久毛片| 欧美精品一区二区三区蜜桃视频| 乱人伦中文视频在线| 国产精品久久久久国产a级| 午夜先锋成人动漫在线| 霍思燕三级露全乳照| 国产成人精品在线看| 欧美第一页在线观看| 欧美美女网站色| 137大胆人体在线观看| 国产精品6699| 国产一区二区区别| wwwxxx黄色片| 久久香蕉国产线看观看99| 日韩免费不卡视频| 亚洲第一级黄色片| 91福利区在线观看| 国产在线播放一区二区| 1024成人| 噜噜噜在线视频| 大桥未久av一区二区三区| 无码国精品一区二区免费蜜桃| 久久久久亚洲精品国产| 国产精品毛片av| 国产69精品久久久久999小说| 成人av在线资源网站| 天天做天天爱夜夜爽| 日韩精品在线免费播放| 91精品产国品一二三产区| 热re99久久精品国产99热| 石原莉奈在线亚洲三区| 精品亚洲aⅴ无码一区二区三区| 色999日韩国产欧美一区二区| 免费福利在线观看| 国产精品久久久久aaaa九色| 日韩大片在线播放| 伊人色在线视频| 亚洲一区二区在线观看视频 | 精品国产一区二区三区2021| 91精品国产吴梦梦| 福利一区二区在线| 天天综合网入口| 亚洲一区二区久久久| 亚洲资源在线| 久无码久无码av无码| 久久只精品国产| 中文字字幕在线观看| 久久天天躁日日躁| 豆花视频一区二区| 国产日韩一区二区在线| 中文字幕的久久| 精品毛片一区二区三区| 91chinesevideo永久地址| 欧美三级情趣内衣| 九九九久久久久久久| 午夜电影一区二区三区| 国产精品影院在线| 91精品久久久久久久久青青| 激情久久久久| 亚洲精品91在线| 日韩视频免费直播| 波多野结衣亚洲| 欧美 另类 交| 91久色porny| 国产视频手机在线观看| 欧美一级在线亚洲天堂| 欧美3p在线观看| 国产二级一片内射视频播放| 欧美综合天天夜夜久久| 青草在线视频| 日韩福利在线| 成人的网站免费观看| 一区二区的视频| 91成人在线播放| 欧美福利影院| 免费看裸体网站| 亚洲电影成人av99爱色| 成人亚洲精品| 日本成人黄色网| 五月激情综合色|