国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java虛擬機運行時棧的棧幀

Java虛擬機運行時棧的棧幀

2022-01-17 11:40沒頭腦遇到不高興 Java教程

本節將會介紹一下Java虛擬機棧中的棧幀,會對棧幀的組成部分(局部變量表、操作數棧、動態鏈接、方法出口)分別進行介紹,最后還會通過javap命令反解析編譯后的.class文件,進行分析方法執行時的局部變量表、操作數棧等

 

Java虛擬機棧概述

Java虛擬機棧(Java Virtual Machine Stacks)是線程私有的,它的生命周期與線程相同。虛擬機棧描述的是Java方法執行的內存模型:棧幀(Stack Frame)是用于支持Java虛擬機進行方法調用和執行的數據結構,它是虛擬機棧中的棧元素。每個方法在執行的同到都會創建一個棧幀用于存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。

在編譯程序代碼的時候,棧幀中需要多大的局部變量表,多深的操作數棧都已經完全確定了,并且寫入到方法表的Code屬性之中,因此一個棧幀需要分配多少內存,不會受到程序運行期變量數據的影響,而僅僅取決于具體的虛擬機實現。

每一個方法從調用直至執行完成的過程,就對應著一個棧幀在虛擬棧中從入棧到出棧的過程(說人話就是要執行一個方法,將該方法的棧幀壓入棧頂,方法執行完成其棧幀出棧)。在JVM里面,棧幀的操作只有兩種:出棧和入棧。正在被線程執行的方法稱為當前線程方法,而該方法的棧幀就稱為當前幀,執行引擎運行時只對當前棧幀有效。

Java虛擬機運行時棧的棧幀

下面對棧幀的每個組成部分分別介紹一下。

 

局部變量表

局部變量表(Local Variable Table)是一組變量值存儲空間,用于存放方法參數和方法內部定義的局部變量。在Java程序編譯為Class文件時就在方法的code屬性的max_locals數據項中確定了該方法所需要分配的局部變量表的最大容量。

局部變量表的容量以變量槽(Variable Slot,下稱Slot)為最小單位,虛擬機規范中并沒有明確指明一個Slot應占用的內存空間大小,只是很有導向性地說到每個引都應該能存放一個boolean、byte、char、short,int,float、reference或returnAddress類型的數據,這8種數類都可以使用32位或更小的物理存來存放,但這種描述與明確指出 "每個Slot占用32位長度的內存空間" 是有一些差別的,它運行Slot的長度可以隨著處理器、操作系統或虛擬機的不同而發生變化。只要保證使在64位虛擬機中使用了64位的物理內存空間去實現一個Slot,虛擬機仍要使用對齊和補白的手段讓Slot在外觀上看起來與32位擬機中的一致。

一個Slot可以存放一個32位以內的數據類型,Java中占用32位以內的數據類型有boolean、byte、char、short、float、reference和returnAddress8種類型。第7種reference類表示對一個對象實例的引用,虛擬機規范既沒有說明它的長度,也沒有明確指出這種引用應有怎樣的結構。但是一般來說,虛擬機實現至少都應當能通過這個引用做到兩點,一是從此引用直接或間接地查找到對象在Java堆中的數據存放的起始地址索引,二是此引用中直接或間接地查找到對象所屬數據類型在方法區中的存儲的類型信息。第8種即returnAddress類型目前已經很少見了,現在已經由異常表代替。

對于64位的數據類型,虛擬機會以高位對齊的方式為其分配兩個連續的引Slot空間。Java語言中明確的(reference類型則可能是32位也可能是64位),64位的數據類型只有long和double兩種。虛擬機通過索引定位的方式使用局部變量表,索引值的范圍是從0開始至局部變量表最大的Slot數量。如果訪問的是32位數據類型的變量,索引 n 就代表了使用第n個Slot,如果是64位數據類型的變量,則說明會同時使用n和n+1兩個Slot對于兩個相鄰的共同存放一個64位數據的兩個Slot,不允許采用任何方式單獨訪問其中的某一個,Java虛擬機規范中明確要求了如果遇到進行這種操作的字節碼序列,虛擬機應該在類加載的校驗階段拋出異常。

如果是實例方法(非static的方法),那么局部變量表中第0位索引的Slot默認是用于傳遞方法所屬對象實例的引用"this"。其余參數則按照參數表的順序來排列,占用從1開始的局部變量Slot,參數表分配完畢后,再根據方法體內部定義的變量順序和作用域分配其余的Slot(比如方法method(int a1,inta2),參數表為a1和a2,則局部變量表索引0、1、2則分別存儲了this指針、a1、a2,如果方法內部有其他內部變量,則在局部變量表中存在a2之后的位置)。

Java虛擬機運行時棧的棧幀

為了盡可能節省棧幀空間,局部變量表中的Slot是可以重用的,方法體中定義的變量,其作用域并不一定會覆蓋整個方法體,如果當前字節碼PC計數器的值已經超出了某個變量的作用域,那這個變量對應的Slot就可以交給其他變量使用。

局部變量不像的類成員變量那樣存在"準備階段"。我們知道類變量有兩次賦初始值的過程,一次在準備階段,賦予系統初始值;另外一次在初始化階段,賦予程序員定義的初始值。因此,即使在初始化階段程序員沒有為類變量賦值也沒有關系,類變量仍然具有一個確定的初始值。但局部變量就不一樣,如果一個局部變量定義了但沒有賦初始值是不能使用的,不要認為Java中任何情況下都存在諸如整型變量默認為0,布爾型變量默認為false等這樣的默認值。

 

操作數棧

操作數棧(Operand Stack)也常稱為操作棧,它是一個后入先出(Last In First out,LIFO)棧。同局部變量表一樣,操作數棧的最大深度也在編譯的時候寫入到code屬性的max_stacks數據項中。操作數棧的每一個元素可以是任意的Java數據類型,包括long和double。32位數據類型所占的棧容量為1,64位數據類型所占的棧容量為2。在方法執行的任何時候,操作數棧的深度都不會超過在maxstacks數據項中設定的最大值。

當一個方法剛剛開始執行的時候,這個方法的操作數棧是空的,在方法的執行過程中,會有各種字節碼指令往操作數棧中寫入和提取內容,也就是出棧/入棧操作。例如,在做算術運算的時候是通過操作數棧來進行的,又或者在調用其他方法的時候是通過操作數棧來進行參數傳遞的。舉個例子,整數加法的字節碼指令iadd在運行的時候操作數棧中最接近棧頂的兩個元素已經存入了兩個int型的數值,當執行這個指令時,會將這兩個int值出棧并相加,然后將相加的結果入棧。

Java虛擬機的解釋執行引擎稱為“基于棧的執行引擎”,其中所指的“棧”就是操作數棧。如果當前線程請求的棧深度大于虛擬機所允許的最大深度,將拋出StackOverflowError異常。

 

動態連接

每個棧幀都包含一個指向運行時常量池中該棧幀所屬方法的引用,持有這個引用是為了支持方法調用過程中的動態連接(Dynamic Linking)。Class文件的常量池中存有大量的符號引用,字節碼中的方法調用指令就以常量池中指向方法的符號引用作為參數。這些符號引用一部分會在類加載階段或者第一次使用的時候就轉化為直接引用,這種轉化稱為靜態解析。另外一部分將在每一次運行期間轉化為直接引用,這部分稱為動態連接。

Java代碼在進行Javac編譯的時候,并不像C和C++那樣有“連接”這一步驟,而是在虛擬機加載Class文件的時候進行動態連接。也就是說,在Class文件中不會保存各個方法、字段的最終內存布局信息,因此這些字段、方法的符號引用不經過運行期轉換的話無法得到真正的內存入口地址,也就無法直接被虛擬機使用。當虛擬機運行時,需要從常量池獲得對應的符號引用,再在類創建時或運行時解析、翻譯到具體的內存地址之中。

Math math=new Math();
math.compute();//調用實例方法compute()

以上面兩行代碼為例,解釋一下動態連接:math.compute()調用時compute()叫符號,需要通過compute()這個符號去到常量池中去找到對應方法的符號引用,運行時將通過符號引用找到方法的字節碼指令的內存地址。

 

方法的返回地址

當一個方法開始執行后,只有兩種方式可以退出這個方法。第一種方式是執行引擎遇任意一個方法返回的字節碼指令,這時候可能會有返回值傳遞給上層的方法調用者(調用當前方法的方法稱為調用者),這種退出方法的方式稱為正常完成出口(Normal Method Invocation Completion)。另外一種退出方式是,在方法執行過程中遇到了異常,并且這個異常沒有在方法體內得到處理,無論是Java虛擬機內部產生的異常,還是代碼中使用athrow字節碼指令產生的異常,只要在本方法的異常表中沒有搜索到匹配的異常處理器,就會導致方法退出,這種退出方法的方式稱為異常完成出口(Abrupt Method Invocation Completion)。一個方法使用異常完成出口的方式退出,是不會給它的上層調用者產生任何返回值的。

無論采用何種退出方式,在方法退出之后,都需要返回到方法被調用的位置,程序才能繼續執行,方法返回時可能需要在棧幀中保存一些信息,用來幫助恢復它的上層方法的執行狀態。一般來說,方法正常退出時,調用者的PC計數器的值可以作為返回地址,棧幀中很可能會保存這個計數器值。而方法異常退出時,返回地址是要通過異常處理器表來確定的,棧幀中一般不會保存這部分信息。方法退出的過程實際上就等同于把當前棧幀出棧,因此退出時可能執行的操作有:恢復上層方法的局部變量表和操作數棧,把返回值(如果有的話)壓入調用者棧幀的操作數棧中,調整pc計數器的值以指向方法調用指令后面的一條指令等。

 

結合javap命令理解棧幀

上面進行了大段的文文字介紹,還是不太好理解,下面我們通過javap命令來分析一下方法中的操作指令、局部變量表、操作數棧等。

javap是jdk自帶的反解析工具。它的作用就是根據class字節碼文件,反解析出當前類對應的code區(匯編指令)、本地變量表、異常表和代碼行偏移量映射表、常量池等等信息。下面是其用法說明:

D:wyonlinemyworkspacesframeworkTestincomwkpjvm>javap
用法: javap <options> <classes>
其中, 可能的選項包括:
  -help  --help  -?        輸出此用法消息
  -version                 版本信息
  -v  -verbose             輸出附加信息
  -l                       輸出行號和本地變量表
  -public                  僅顯示公共類和成員
  -protected               顯示受保護的/公共類和成員
  -package                 顯示程序包/受保護的/公共類
                           和成員 (默認)
  -p  -private             顯示所有類和成員
  -c                       對代碼進行反匯編
  -s                       輸出內部類型簽名
  -sysinfo                 顯示正在處理的類的
                           系統信息 (路徑, 大小, 日期, MD5 散列)
  -constants               顯示最終常量
  -classpath <path>        指定查找用戶類文件的位置
  -cp <path>               指定查找用戶類文件的位置
  -bootclasspath <path>    覆蓋引導類文件的位置

下面我們寫一個簡單的Java程序:

package com.wkp.jvm;
 
public class Math {
 
	public static final Integer CONSTANT=666;
	
	public int compute() {//一個方法對應一塊棧幀內存區域
		int a=3;
		int b=5;
		int c=(a+b)*10;
		return c;
	}
	
	public static void main(String[] args) {
		Math math=new Math();
		math.compute();
	}
}

然后進入到Math.class所在目錄執行: javap -c Math.class > Math.txt 命令,將Math.class字節碼文件反匯編然后輸出到Math.txt文件中:

Java虛擬機運行時棧的棧幀

然后我們查看Math.txt的內容如下:我們重點分析下compute方法內的指令,其內部的指令后面我加了注釋(這里我是參考上一節的《JVM字節碼指令集大全及其介紹》,感興趣的話可以看一看),注釋中的棧就是指的棧幀中的操作數棧,本地變量表就是指的局部變量表。

Compiled from "Math.java"
public class com.wkp.jvm.Math {
  public static final java.lang.Integer CONSTANT;
 
  static {};
    Code:
       0: sipush        666
       3: invokestatic  #10                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       6: putstatic     #16                 // Field CONSTANT:Ljava/lang/Integer;
       9: return
 
  public com.wkp.jvm.Math();
    Code:
       0: aload_0
       1: invokespecial #21                 // Method java/lang/Object."<init>":()V
       4: return
 
  public int compute();
    Code:
       0: iconst_3			//將int類型的3推送至棧頂
       1: istore_1			//將棧頂int類型數值(上面的3)出棧并存入第二個本地變量
       2: iconst_5			//將int類型的5推送至棧頂
       3: istore_2			//將棧頂int類型數值(上面的5)出棧并存入第三個本地變量
       4: iload_1			//將第二個int型本地變量(上面的3)推送至棧頂
       5: iload_2			//將第三個int型本地變量(上面的5)推送至棧頂
       6: iadd				//將棧頂兩int型數值出棧,然后相加并將結果壓入棧頂
       7: bipush        10	        //將常量值10推送至棧頂
       9: imul				//將棧頂兩int型數值出棧,然后相乘并將結果壓入棧頂
      10: istore_3			//將棧頂int類型數值(上面的乘積)出棧并存入第四個本地變量
      11: iload_3			//將第四個int類型本地變量推送至棧頂
      12: ireturn			//從當前方法返回int類型值
 
  public static void main(java.lang.String[]);
    Code:
       0: new           #1                  // class com/wkp/jvm/Math
       3: dup
       4: invokespecial #33                 // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #34                 // Method compute:()I
      12: pop
      13: return
}

下面我們通過圖示簡單表示一下上面compute方法中指令操作時關于本地變量表、操作數棧的情況:

我們先看下第一行 0: iconst_3 //將int類型的3推送至棧頂,可以看到下圖3已經被入棧到操作數棧的棧頂。

Java虛擬機運行時棧的棧幀

我們再看下第二行 1: istore_1 //將棧頂int類型數值(上面的3)出棧并存入第二個本地變量,將上圖中棧頂的3出棧然后存入本地表中第二個位置,如下圖所示:

Java虛擬機運行時棧的棧幀

第三行、第四行跟上面的一二行指令類似,第四行指令執行后變成如下所示:

Java虛擬機運行時棧的棧幀

第五行、第六行中 4: iload_1 //將第二個int型本地變量(上面的3)推送至棧頂; 5: iload_2 //將第三個int型本地變量(上面的5)推送至棧頂,即將局部變量表中的3和5依次壓入棧頂,如下圖所示:

Java虛擬機運行時棧的棧幀

然后第七行執行iadd操作,將棧頂的兩個int類型數據5和3出棧相加,將得到的和壓入棧頂,得到如下結果:

Java虛擬機運行時棧的棧幀

后面的指令操作過程與上面類似,執行完第12行的iload_3指令之后,會得到如下圖所示:

Java虛擬機運行時棧的棧幀

關于局部變量表的信息,還可以通過javap -l 命令查看如下圖所示,另外還可以通過Idea中的jclasslib 查看。

LocalVariableTable表示的就是局部變量表的信息:

public int compute();
    LineNumberTable:
      line 8: 0
      line 9: 2
      line 10: 4
      line 11: 11
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      13     0  this   Lcom/wkp/jvm/Math;
          2      11     1     a   I
          4       9     2     b   I
         11       2     3     c   I

我們還可以通過 javap -c Math.class > Math.txt 查看更多的信息如下:我們可以看到 9: invokevirtual #34 // Method compute:() 中的 #34 可以在常量池中找到 #34 = Methodref #1.#35 // com/wkp/jvm/Math.compute:()也就是方法的符號引用,運行時通過符號引用解析出來方法的執行指令的內存地址,這個其實就是動態連接。

Classfile /D:/wyonline/myworkspaces/framework/Test/bin/com/wkp/jvm/Math.class
  Last modified 2019-8-24; size 761 bytes
  MD5 checksum be0cdf4bcd037929d3fe0af86d44a837
  Compiled from "Math.java"
public class com.wkp.jvm.Math
  minor version: 0
  major version: 52		//魔數
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:		//常量池
   #1 = Class              #2             // com/wkp/jvm/Math
   #2 = Utf8               com/wkp/jvm/Math
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               CONSTANT
   #6 = Utf8               Ljava/lang/Integer;
   #7 = Utf8               <clinit>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Methodref          #11.#13        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
  #11 = Class              #12            // java/lang/Integer
  #12 = Utf8               java/lang/Integer
  #13 = NameAndType        #14:#15        // valueOf:(I)Ljava/lang/Integer;
  #14 = Utf8               valueOf
  #15 = Utf8               (I)Ljava/lang/Integer;
  #16 = Fieldref           #1.#17         // com/wkp/jvm/Math.CONSTANT:Ljava/lang/Integer;
  #17 = NameAndType        #5:#6          // CONSTANT:Ljava/lang/Integer;
  #18 = Utf8               LineNumberTable
  #19 = Utf8               LocalVariableTable
  #20 = Utf8               <init>
  #21 = Methodref          #3.#22         // java/lang/Object."<init>":()V
  #22 = NameAndType        #20:#8         // "<init>":()V
  #23 = Utf8               this
  #24 = Utf8               Lcom/wkp/jvm/Math;
  #25 = Utf8               compute
  #26 = Utf8               ()I
  #27 = Utf8               a
  #28 = Utf8               I
  #29 = Utf8               b
  #30 = Utf8               c
  #31 = Utf8               main
  #32 = Utf8               ([Ljava/lang/String;)V
  #33 = Methodref          #1.#22         // com/wkp/jvm/Math."<init>":()V
  #34 = Methodref          #1.#35         // com/wkp/jvm/Math.compute:()I
  #35 = NameAndType        #25:#26        // compute:()I
  #36 = Utf8               args
  #37 = Utf8               [Ljava/lang/String;
  #38 = Utf8               math
  #39 = Utf8               SourceFile
  #40 = Utf8               Math.java
{
  public static final java.lang.Integer CONSTANT;
    descriptor: Ljava/lang/Integer;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
 
  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: sipush        666
         3: invokestatic  #10                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         6: putstatic     #16                 // Field CONSTANT:Ljava/lang/Integer;
         9: return
      LineNumberTable:
        line 5: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
 
  public com.wkp.jvm.Math();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #21                 // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/wkp/jvm/Math;
 
  public int compute();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=1
         0: iconst_3
         1: istore_1
         2: iconst_5
         3: istore_2
         4: iload_1
         5: iload_2
         6: iadd
         7: bipush        10
         9: imul
        10: istore_3
        11: iload_3
        12: ireturn
      LineNumberTable:
        line 8: 0
        line 9: 2
        line 10: 4
        line 11: 11
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     0  this   Lcom/wkp/jvm/Math;
            2      11     1     a   I
            4       9     2     b   I
           11       2     3     c   I
 
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #1                  // class com/wkp/jvm/Math
         3: dup
         4: invokespecial #33                 // Method "<init>":()V
         7: astore_1
         8: aload_1
         9: invokevirtual #34                 // Method compute:()I
        12: pop
        13: return
      LineNumberTable:
        line 15: 0
        line 16: 8
        line 17: 13
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      14     0  args   [Ljava/lang/String;
            8       6     1  math   Lcom/wkp/jvm/Math;
}
SourceFile: "Math.java"

參考:《深入理解Java虛擬機第二版》、《Java虛擬機規范 JavaSE8版》

到此這篇關于Java虛擬機運行時棧的棧幀的文章就介紹到這了,更多相關Java 虛擬機 棧幀內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/u012988901/article/details/100043857

延伸 · 閱讀

精彩推薦
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 99精品视频在线观看 | 欧美一级裸体视频 | av天天网| 成人午夜精品久久久久久久3d | 成人在线视频免费观看 | 久久大 | 99看| 中文字幕一区在线观看视频 | 亚洲国产精品激情在线观看 | 国产中文字幕一区 | 91久久精品日日躁夜夜躁国产 | 亚洲精品第一 | 精品一区二区三区在线视频 | 国产片在线观看免费观看 | 中文字幕日韩一区二区不卡 | 国产剧情一区二区 | 久久99精品久久久久久噜噜 | 国产成人久久一区二区三区 | 一本大道香蕉大a√在线 | 色婷婷综合在线 | 欧美一区二区三区在线视频 | av免费观看网站 | 免费成年人视频在线观看 | 免费看黄色影片 | 欧美视频在线播放 | 欧美一区二区在线观看 | 日本精品中文字幕 | 在线视频 亚洲 | 国产露脸国语对白在线 | 青青草免费在线 | 国产精品资源在线 | 99精品视频在线观看 | 国产精品一区二区三区免费视频 | 中文字幕在线观看精品视频 | 亚洲精品日韩精品 | 中文字幕av在线播放 | 激情一区二区三区 | 国产一区二区在线免费观看 | 日韩大片在线观看 | 国产欧美一区二区 | www.天天草 |