日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JVM【带着问题去学习 02】数据结构栈+本地方法栈+虚拟机栈+JVM栈运行原理

發(fā)布時間:2024/10/6 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM【带着问题去学习 02】数据结构栈+本地方法栈+虚拟机栈+JVM栈运行原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.數(shù)據(jù)結(jié)構(gòu)棧

棧是一種比較簡單的數(shù)據(jù)結(jié)構(gòu),后進先出。棧本身是一個線性表,但是這個表中只有一端允許數(shù)據(jù)的進出。棧的常用操作包括入棧push和出棧pop,對應(yīng)于數(shù)據(jù)的壓入和彈出。由于棧后進先出的特性,常可以作為數(shù)據(jù)操作的臨時容器,對數(shù)據(jù)的順序進行調(diào)控。

2.本地方法棧

2.1 本地方法(Native Method)

本地方法是由非 Java 語言編寫的,編譯成和處理器相關(guān)的機器代碼。它保存在動態(tài)鏈接庫中,Windows 系統(tǒng)即 .dll 文件中,格式是各個平臺專有的。Java 方法是與平臺無關(guān)的,但是本地方法不是,運行中的 Java 方法調(diào)用本地方法時虛擬機會裝載包含這個本地方法的動態(tài)庫,并調(diào)用這個本地方法。

通過本地方法,Java 程序可以直接訪問底層操作系統(tǒng)的資源,調(diào)用本地方法會使程序變得與平臺相關(guān),因為本地方法的動態(tài)庫是與平臺相關(guān)的,此外使用本地方法還可能把程序變得和特定的 Java 平臺實現(xiàn)相關(guān)。而本地方法接口(Java Native Interface JNI)使得本地方法可以在特定主機系統(tǒng)的任何一個 Java 平臺實現(xiàn)上運行。如果希望使用特定主機上的資源,它們又無法通過 Java API 訪問,那么可以寫一個平臺相關(guān)的 Java 程序來調(diào)用本地方法,如果希望保證程序的平臺無關(guān)性,那么只能通過 Java API 來訪問底層系統(tǒng)資源。

標(biāo)識符 native 可以與所有其它的 Java 標(biāo)識符連用,但是 abstrat 除外。因為 native 表示這些方法是有實現(xiàn)體的,只不過這些實現(xiàn)體是非 Java 的,但是abstract 卻顯然的指明這些方法無實現(xiàn)體。native 與其它 Java 標(biāo)識符連用時,其意義同非本地并無差別,比如 native static 表明這個方法可以在不產(chǎn)生類的實例時直接調(diào)用,比如用一個native method 去調(diào)用一個 C 的類庫時。

2.2 本地方法棧(Native Method Stack)

本地方法棧用于管理本地方法的調(diào)用是線程私有的,并不是所有 JVM 都支持本地方法。因為 JVM 規(guī)范并沒有明確要求本地方法棧的使用語言、具體實現(xiàn)方式、數(shù)據(jù)結(jié)構(gòu)等。如果 JVM 產(chǎn)品不打算支持 native 方法,也可以無需實現(xiàn)本地方法棧。

  • 本地方法是使用C語言實現(xiàn)的

  • 它的具體做法是 Native Method Stack 中登記native方法,在 Execution Engine 執(zhí)行時加載本地方法庫。線程調(diào)用本地方法就不再受虛擬機限制了,它和虛擬機擁有同樣的權(quán)限。

  • 本地方法可以通過 JNI 來訪問虛擬機內(nèi)部的運行時數(shù)據(jù)區(qū),它甚至可以直接使用本地處理器中的寄存器,直接從本地內(nèi)存的堆中分配任意數(shù)量的內(nèi)存。

  • 在 Hotspot JVM 中,直接將本地方棧和虛擬機棧合二為一。

本地方法棧與虛擬機棧的作用是相似的,都會拋出OutOfMemoryError和StackOverFlowError,都是線程私有的,主要的區(qū)別在于:

  • 虛擬機棧執(zhí)行的是 Java 方法
  • 本地方法棧執(zhí)行的是 native 方法

3.虛擬機棧

虛擬機棧(Java Virtual Machine Stacks)。每個線程在創(chuàng)建的時候都會創(chuàng)建一個虛擬機棧,其內(nèi)部保存的棧幀(Stack Frame),對應(yīng)著 Java 方法調(diào)用,是線程私有的,生命周期和線程一致。主管 Java 程序的運行,它保存方法的局部變量、部分結(jié)果,并參與方法的調(diào)用和返回。特點:

  • 是一種快速有效的分配存儲方式,訪問速度僅次于程序計數(shù)器。
  • JVM 直接對虛擬機棧的操作只有兩個:每個方法執(zhí)行,伴隨著入棧(進棧/壓棧),方法執(zhí)行結(jié)束出棧
  • 棧不存在垃圾回收問題。

棧中可能出現(xiàn)的異常:

Java 虛擬機規(guī)范允許 Java虛擬機棧的大小是動態(tài)的或者是固定不變的

  • 如果采用固定大小的 Java 虛擬機棧,那每個線程的 Java 虛擬機棧容量可以在線程創(chuàng)建的時候獨立選定。如果線程請求分配的棧容量超過 Java 虛擬機棧允許的最大容量,Java 虛擬機將會拋出一個 StackOverflowError 異常
  • 如果 Java 虛擬機棧可以動態(tài)擴展,并且在嘗試擴展的時候無法申請到足夠的內(nèi)存,或者在創(chuàng)建新的線程時沒有足夠的內(nèi)存去創(chuàng)建對應(yīng)的虛擬機棧,那 Java 虛擬機將會拋出一個OutOfMemoryError異常

可以通過參數(shù)-Xss來設(shè)置線程的最大棧空間,棧的大小直接決定了函數(shù)調(diào)用的最大可達深度。

每個**棧幀(Stack Frame)**中存儲著:

  • 局部變量表(Local Variables)
  • 操作數(shù)棧(Operand Stack)(或稱為表達式棧)
  • 動態(tài)鏈接(Dynamic Linking):指向運行時常量池的方法引用
  • 方法返回地址(Return Address):方法正常退出或異常退出的地址
  • 一些附加信息

3.1 局部變量表

局部變量表也被稱為局部變量數(shù)組或者本地變量表,是一組變量值存儲空間,主要用于存儲方法參數(shù)和定義在方法體內(nèi)的局部變量,包括編譯器可知的各種 Java 虛擬機基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference類型,它并不等同于對象本身,可能是一個指向?qū)ο笃鹗嫉刂返囊弥羔?#xff0c;也可能是指向一個代表對象的句柄或其他與此相關(guān)的位置)和returnAddress 類型(指向了一條字節(jié)碼指令的地址,已被異常表取代)

由于局部變量表是建立在線程的棧上,是線程的私有數(shù)據(jù),因此不存在數(shù)據(jù)安全問題局部變量表所需要的容量大小是編譯期確定下來的,并保存在方法的 Code 屬性的maximum local variables 數(shù)據(jù)項中。在方法運行期間是不會改變局部變量表的大小的

方法嵌套調(diào)用的次數(shù)由棧的大小決定。一般來說,棧越大,方法嵌套調(diào)用次數(shù)越多。對一個函數(shù)而言,它的參數(shù)和局部變量越多,使得局部變量表膨脹,它的棧幀就越大,以滿足方法調(diào)用所需傳遞的信息增大的需求。進而函數(shù)調(diào)用就會占用更多的棧空間,導(dǎo)致其嵌套調(diào)用次數(shù)就會減少。局部變量表中的變量只在當(dāng)前方法調(diào)用中有效。在方法執(zhí)行時,虛擬機通過使用局部變量表完成參數(shù)值到參數(shù)變量列表的傳遞過程。當(dāng)方法調(diào)用結(jié)束后,隨著方法棧幀的銷毀,局部變量表也會隨之銷毀。

參數(shù)值的存放總是在局部變量數(shù)組的 index0 開始,到數(shù)組長度 -1 的索引結(jié)束

局部變量表最基本的存儲單元是Slot(變量槽),在局部變量表中,32位以內(nèi)的類型只占用一個Slot(包括returnAddress類型),64位的類型(long和double)占用兩個連續(xù)的 Slot

  • byte、short、char 在存儲前被轉(zhuǎn)換為int,boolean也被轉(zhuǎn)換為int,0 表示 false,非 0 表示 true
  • long 和 double 則占據(jù)兩個 Slot

JVM 會為局部變量表中的每一個 Slot 都分配一個訪問索引,通過這個索引即可成功訪問到局部變量表中指定的局部變量值,索引值的范圍從 0 開始到局部變量表最大的 Slot 數(shù)量,當(dāng)一個實例方法被調(diào)用的時候,它的方法參數(shù)和方法體內(nèi)部定義的局部變量將會按照順序被復(fù)制到局部變量表中的每一個 Slot 上,如果需要訪問局部變量表中一個64bit的局部變量值時,只需要使用前一個索引即可。(比如:訪問 long 或double 類型變量,不允許采用任何方式單獨訪問其中的某一個 Slot)

如果當(dāng)前幀是由構(gòu)造方法或?qū)嵗椒▌?chuàng)建的,那么該對象引用 this 將會存放在 index 為 0 的 Slot 處,其余的參數(shù)按照參數(shù)表順序繼續(xù)排列(這里就引出一個問題:靜態(tài)方法中為什么不可以引用 this,就是因為this 變量不存在于當(dāng)前方法的局部變量表中)棧幀中的局部變量表中的槽位是可以重用的,如果一個局部變量過了其作用域,那么在其作用域之后申明的新的局部變量就很有可能會復(fù)用過期局部變量的槽位,從而達到節(jié)省資源的目的

  • 在棧幀中,與性能調(diào)優(yōu)關(guān)系最為密切的就是局部變量表。在方法執(zhí)行時,虛擬機使用局部變量表完成方法的傳遞
  • 局部變量表中的變量也是重要的垃圾回收根節(jié)點,只要被局部變量表中直接或間接引用的對象都不會被回收

3.2 操作數(shù)棧

  • 每個獨立的棧幀中除了包含局部變量表之外,還包含一個后進先出(Last-In-First-Out)的操作數(shù)棧,也可以稱為表達式棧(Expression Stack)
  • 操作數(shù)棧,在方法執(zhí)行過程中,根據(jù)字節(jié)碼指令,往操作數(shù)棧中寫入數(shù)據(jù)或提取數(shù)據(jù),即入棧(push)、出棧(pop)
  • 某些字節(jié)碼指令將值壓入操作數(shù)棧,其余的字節(jié)碼指令將操作數(shù)取出棧。使用它們后再把結(jié)果壓入棧。比如,執(zhí)行復(fù)制、交換、求和等操作
概述
  • 操作數(shù)棧,主要用于保存計算過程的中間結(jié)果,同時作為計算過程中變量臨時的存儲空間

  • 操作數(shù)棧就是 JVM 執(zhí)行引擎的一個工作區(qū),當(dāng)一個方法剛開始執(zhí)行的時候,一個新的棧幀也會隨之被創(chuàng)建出來,此時這個方法的操作數(shù)棧是空的

  • 每一個操作數(shù)棧都會擁有一個明確的棧深度用于存儲數(shù)值,其所需的最大深度在編譯期就定義好了,保存在方法的 Code 屬性的 max_stack 數(shù)據(jù)項中

  • 棧中的任何一個元素都可以是任意的 Java 數(shù)據(jù)類型

    • 32bit 的類型占用一個棧單位深度
    • 64bit 的類型占用兩個棧單位深度
  • 操作數(shù)棧并非采用訪問索引的方式來進行數(shù)據(jù)訪問的,而是只能通過標(biāo)準(zhǔn)的入棧和出棧操作來完成一次數(shù)據(jù)訪問

  • 如果被調(diào)用的方法帶有返回值的話,其返回值將會被壓入當(dāng)前棧幀的操作數(shù)棧中,并更新PC寄存器中下一條需要執(zhí)行的字節(jié)碼指令

  • 操作數(shù)棧中元素的數(shù)據(jù)類型必須與字節(jié)碼指令的序列嚴(yán)格匹配,這由編譯器在編譯期間進行驗證,同時在類加載過程中的類檢驗階段的數(shù)據(jù)流分析階段要再次驗證

  • 另外,我們說Java虛擬機的解釋引擎是基于棧的執(zhí)行引擎,其中的棧指的就是操作數(shù)棧

棧頂緩存(Top-of-stack-Cashing)

HotSpot 的執(zhí)行引擎采用的并非是基于寄存器的架構(gòu),但這并不代表 HotSpot VM 的實現(xiàn)并沒有間接利用到寄存器資源。寄存器是物理 CPU 中的組成部分之一,它同時也是 CPU 中非常重要的高速存儲資源。一般來說,寄存器的讀/寫速度非常迅速,甚至可以比內(nèi)存的讀/寫速度快上幾十倍不止,不過寄存器資源卻非常有限,不同平臺下的CPU 寄存器數(shù)量是不同和不規(guī)律的。寄存器主要用于緩存本地機器指令、數(shù)值和下一條需要被執(zhí)行的指令地址等數(shù)據(jù)。

基于棧式架構(gòu)的虛擬機所使用的零地址指令更加緊湊,但完成一項操作的時候必然需要使用更多的入棧和出棧指令,這同時也就意味著將需要更多的指令分派(instruction dispatch)次數(shù)和內(nèi)存讀/寫次數(shù)。由于操作數(shù)是存儲在內(nèi)存中的,因此頻繁的執(zhí)行內(nèi)存讀/寫操作必然會影響執(zhí)行速度。為了解決這個問題,HotSpot JVM設(shè)計者們提出了棧頂緩存技術(shù),將棧頂元素全部緩存在物理 CPU 的寄存器中,以此降低對內(nèi)存的讀/寫次數(shù),提升執(zhí)行引擎的執(zhí)行效率

3.3 動態(tài)鏈接(指向運行時常量池的方法引用)

  • 每一個棧幀內(nèi)部都包含一個指向運行時常量池中該棧幀所屬方法的引用。包含這個引用的目的就是為了支持當(dāng)前方法的代碼能夠?qū)崿F(xiàn)動態(tài)鏈接(Dynamic Linking)。
  • 在 Java 源文件被編譯到字節(jié)碼文件中時,所有的變量和方法引用都作為符號引用(Symbolic Reference)保存在 Class 文件的常量池中。比如:描述一個方法調(diào)用了另外的其他方法時,就是通過常量池中指向方法的符號引用來表示的,那么動態(tài)鏈接的作用就是為了將這些符號引用轉(zhuǎn)換為調(diào)用方法的直接引用
JVM 是如何執(zhí)行方法調(diào)用的

方法調(diào)用不同于方法執(zhí)行,方法調(diào)用階段的唯一任務(wù)就是確定被調(diào)用方法的版本(即調(diào)用哪一個方法),暫時還不涉及方法內(nèi)部的具體運行過程。Class 文件的編譯過程中不包括傳統(tǒng)編譯器中的連接步驟,一切方法調(diào)用在 Class文件里面存儲的都是符號引用,而不是方法在實際運行時內(nèi)存布局中的入口地址(直接引用)。也就是需要在類加載階段,甚至到運行期才能確定目標(biāo)方法的直接引用。

在 JVM 中,將符號引用轉(zhuǎn)換為調(diào)用方法的直接引用與方法的綁定機制有關(guān)

  • 靜態(tài)鏈接:當(dāng)一個字節(jié)碼文件被裝載進 JVM 內(nèi)部時,如果被調(diào)用的目標(biāo)方法在編譯期可知,且運行期保持不變時。這種情況下將調(diào)用方法的符號引用轉(zhuǎn)換為直接引用的過程稱之為靜態(tài)鏈接
  • 動態(tài)鏈接:如果被調(diào)用的方法在編譯期無法被確定下來,也就是說,只能在程序運行期將調(diào)用方法的符號引用轉(zhuǎn)換為直接引用,由于這種引用轉(zhuǎn)換過程具備動態(tài)性,因此也就被稱之為動態(tài)鏈接

對應(yīng)的方法的綁定機制為:早期綁定(Early Binding)和晚期綁定(Late Binding)。綁定是一個字段、方法或者類在符號引用被替換為直接引用的過程,這僅僅發(fā)生一次

  • 早期綁定:早期綁定就是指被調(diào)用的目標(biāo)方法如果在編譯期可知,且運行期保持不變時,即可將這個方法與所屬的類型進行綁定,這樣一來,由于明確了被調(diào)用的目標(biāo)方法究竟是哪一個,因此也就可以使用靜態(tài)鏈接的方式將符號引用轉(zhuǎn)換為直接引用。
  • 晚期綁定:如果被調(diào)用的方法在編譯器無法被確定下來,只能夠在程序運行期根據(jù)實際的類型綁定相關(guān)的方法,這種綁定方式就被稱為晚期綁定。
虛方法和非虛方法
  • 如果方法在編譯器就確定了具體的調(diào)用版本,這個版本在運行時是不可變的。這樣的方法稱為非虛方法,比如靜態(tài)方法、私有方法、final方法、實例構(gòu)造器、父類方法都是非虛方法
  • 其他方法稱為虛方法
虛方法表

在面向?qū)ο缶幊讨?#xff0c;會頻繁的使用到動態(tài)分派,如果每次動態(tài)分派都要重新在類的方法元數(shù)據(jù)中搜索合適的目標(biāo)有可能會影響到執(zhí)行效率。為了提高性能,JVM 采用在類的方法區(qū)建立一個虛方法表(virtual method table),使用索引表來代替查找。非虛方法不會出現(xiàn)在表中。

每個類中都有一個虛方法表,表中存放著各個方法的實際入口。

虛方法表會在類加載的連接階段被創(chuàng)建并開始初始化,類的變量初始值準(zhǔn)備完成之后,JVM 會把該類的方法表也初始化完畢。

3.4 方法返回地址(return address)

用來存放調(diào)用該方法的 PC 寄存器的值。

一個方法的結(jié)束,有兩種方式

  • 正常執(zhí)行完成
  • 出現(xiàn)未處理的異常,非正常退出

無論通過哪種方式退出,在方法退出后都返回到該方法被調(diào)用的位置。方法正常退出時,調(diào)用者的 PC 計數(shù)器的值作為返回地址,即調(diào)用該方法的指令的下一條指令的地址。而通過異常退出的,返回地址是要通過異常表來確定的,棧幀中一般不會保存這部分信息。

當(dāng)一個方法開始執(zhí)行后,只有兩種方式可以退出這個方法:

  • 執(zhí)行引擎遇到任意一個方法返回的字節(jié)碼指令,會有返回值傳遞給上層的方法調(diào)用者,簡稱正常完成出口

    一個方法的正常調(diào)用完成之后究竟需要使用哪一個返回指令還需要根據(jù)方法返回值的實際數(shù)據(jù)類型而定

    在字節(jié)碼指令中,返回指令包含 ireturn(當(dāng)返回值是boolean、byte、char、short和int類型時使用)、lreturn、freturn、dreturn以及areturn,另外還有一個 return 指令供聲明為 void 的方法、實例初始化方法、類和接口的初始化方法使用。

  • 在方法執(zhí)行的過程中遇到了異常,并且這個異常沒有在方法內(nèi)進行處理,也就是只要在本方法的異常表中沒有搜索到匹配的異常處理器,就會導(dǎo)致方法退出。簡稱異常完成出口

    方法執(zhí)行過程中拋出異常時的異常處理,存儲在一個異常處理表,方便在發(fā)生異常的時候找到處理異常的代碼。

  • 本質(zhì)上,方法的退出就是當(dāng)前棧幀出棧的過程。此時,需要恢復(fù)上層方法的局部變量表、操作數(shù)棧、將返回值壓入調(diào)用者棧幀的操作數(shù)棧、設(shè)置PC寄存器值等,讓調(diào)用者方法繼續(xù)執(zhí)行下去。

    正常完成出口和異常完成出口的區(qū)別在于:通過異常完成出口退出的不會給他的上層調(diào)用者產(chǎn)生任何的返回值

    3.5 附加信息

    棧幀中還允許攜帶與 Java 虛擬機實現(xiàn)相關(guān)的一些附加信息。例如,對程序調(diào)試提供支持的信息,但這些信息取決于具體的虛擬機實現(xiàn)。

    4.棧運行原理

    • JVM 直接對 Java 棧的操作只有兩個,對棧幀的壓棧出棧,遵循“先進后出/后進先出”原則
    • 在一條活動線程中,一個時間點上,只會有一個活動的棧幀。即只有當(dāng)前正在執(zhí)行的方法的棧幀(棧頂棧幀)是有效的,這個棧幀被稱為當(dāng)前棧幀(Current Frame),與當(dāng)前棧幀對應(yīng)的方法就是當(dāng)前方法(Current Method),定義這個方法的類就是當(dāng)前類(Current Class)
    • 執(zhí)行引擎運行的所有字節(jié)碼指令只針對當(dāng)前棧幀進行操作
    • 如果在該方法中調(diào)用了其他方法,對應(yīng)的新的棧幀會被創(chuàng)建出來,放在棧的頂端,稱為新的當(dāng)前棧幀
    • 不同線程中所包含的棧幀是不允許存在相互引用的,即不可能在一個棧幀中引用另外一個線程的棧幀
    • 如果當(dāng)前方法調(diào)用了其他方法,方法返回之際,當(dāng)前棧幀會傳回此方法的執(zhí)行結(jié)果給前一個棧幀,接著,虛擬機會丟棄當(dāng)前棧幀,使得前一個棧幀重新成為當(dāng)前棧幀
    • Java 方法有兩種返回函數(shù)的方式,一種是正常的函數(shù)返回,使用 return 指令,另一種是拋出異常,不管用哪種方式,都會導(dǎo)致棧幀被彈出

    IDEA 在 debug 時候,可以在 debug 窗口看到 Frames 中各種方法的壓棧和出棧情況

    public class Test {public static void main(String[] args) {test1();}private static void test1() {test2();}private static void test2() {int i = test3();System.out.println(i);}private static int test3() {return 3;} }

    5.相關(guān)問題

    為什么要將堆和棧分開,棧不是也可以存儲數(shù)據(jù)嗎?

    1、從軟件設(shè)計角度分析,棧代表了處理邏輯,堆代表了數(shù)據(jù),這樣分開,使得處理邏輯更清晰。分而治之的思想,這種隔離、模塊化的思想體現(xiàn)在軟件中的很多地方。

    2、堆和棧的分離,使得堆的內(nèi)容可以被多個棧共享(即多個線程訪問同一個對象)。這種共享的收益很多,這種共享提供了一種有效的數(shù)據(jù)交互方式(共享內(nèi)存),另一方面,堆中共享的常量和緩存可以被所有棧訪問,節(jié)省了內(nèi)存。

    3、棧因為運行是需要,比如保存系統(tǒng)運行的上下文,需要地址段的劃分,由于棧只能向上增長,因此限制住棧存儲內(nèi)容的能力,而堆是根據(jù)需要可以動態(tài)增長的,因此棧和堆的拆分,使得堆動態(tài)增長成為可能,相應(yīng)棧只需要記住堆中的一個地址即可。

    4、面向?qū)ο缶褪嵌押蜅5耐昝澜Y(jié)合。其實,面向?qū)ο蠓绞降某绦蚺c以前結(jié)構(gòu)化的程序在執(zhí)行上沒有任何區(qū)別。但是,面向?qū)ο蟮囊?#xff0c;使得對待問題的思考方式發(fā)生了改變,而更接近于自然方式的思考。當(dāng)我們把對象拆開,你會發(fā)現(xiàn),對象的屬性其實就是數(shù)據(jù),存放在堆中;而對象的行為(方法),就是運行邏輯,放在棧中。我們在編寫對象的時候,其實即編寫了數(shù)據(jù)結(jié)構(gòu),也編寫的處理數(shù)據(jù)的邏輯。

    與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

    總結(jié)

    以上是生活随笔為你收集整理的JVM【带着问题去学习 02】数据结构栈+本地方法栈+虚拟机栈+JVM栈运行原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 久久亚洲aⅴ无码精品 | 国产精品一区二区免费 | 黄色电影在线视频 | 成人伊人| 日本网站在线播放 | 欧美成人乱码一二三四区免费 | 日日干天天操 | www.日韩.com| 亚洲人成在线免费观看 | 久久国产香蕉视频 | 尤物193.com| 久久久久久91香蕉国产 | 日本中文字幕网 | 91成人免费电影 | 激情综合五月婷婷 | 亚洲精品嫩草 | 欧美在线视频你懂的 | 风间由美一区二区三区 | 欧美有码视频 | 成人毛片在线观看 | 免费毛片在线 | 免费黄色激情视频 | 牲欲强的熟妇农村老妇女视频 | 国产精品一二三区视频 | 欧美小视频在线观看 | 春色校园激情 | 中文黄色片 | 欧美三级电影在线观看 | 亚州av片 | ass亚洲肉体欣赏pics | 噼里啪啦免费高清看 | 成年人黄色网址 | 色妞www精品视频 | 成人夜晚视频 | 国产精品久久国产精麻豆96堂 | av第一福利 | 国产一区二区黑人欧美xxxx | 色综合天天综合 | 男女午夜爽爽 | 日韩高清成人 | xxxx国产视频 | 日韩精品一区二区电影 | 米奇影视第四色 | 999视频 | 国产精品乱码一区二区 | 日韩涩 | 黑人巨大精品欧美一区二区免费 | 一区二区三区国产在线观看 | 国内少妇精品 | 精品日韩在线 | 亚洲视频91 | 韩国在线不卡 | 久草97| 五月激情六月婷婷 | wwwxxx国产| 蜜桃av在线播放 | 国产成人在线一区二区 | 免费看黄色aaaaaa 片 | 国模视频一区二区 | 红桃视频国产 | 女女同性女同一区二区三区九色 | 亚洲天天操 | 第一页综合| 色视频在线免费观看 | 强伦轩人妻一区二区电影 | 日韩免费一二三区 | 亚洲图片偷拍区 | 人妻少妇精品一区二区三区 | 性五月天 | 国产久草av | 中文字幕11页中文字幕11页 | 国产91九色 | 中文字幕一区二区三区精华液 | 日韩三级在线播放 | 国产电影一区二区三区爱妃记 | 欧美xxxx黑人又粗又长密月 | av影片在线播放 | 亚洲综合网在线观看 | 免费性视频 | av资源在线免费观看 | 中文字幕亚洲一区二区三区 | 香蕉视频91 | 免费三级大片 | 婷婷综合 | 成人免费视频一区二区三区 | 91在线高清| 桃谷绘里香番号 | 天天综合干| 欧美激情欧美激情在线五月 | 成人av图片| 亚洲欧美激情精品一区二区 | 男女啊啊啊视频 | 久久久久久无码精品人妻一区二区 | 狠狠做深爱婷婷综合一区 | 伊人青青 | 亚洲伦理自拍 | 久久久视频在线观看 | 日本一区二区不卡视频 | 色综合久久久久综合体桃花网 |