一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - Java虛擬機(jī)JVM性能優(yōu)化(一):JVM知識(shí)總結(jié)

Java虛擬機(jī)JVM性能優(yōu)化(一):JVM知識(shí)總結(jié)

2019-11-28 14:29junjie JAVA教程

這篇文章主要介紹了Java虛擬機(jī)JVM性能優(yōu)化(一):JVM知識(shí)總結(jié),本文是系列文章的第一篇,后續(xù)篇章請(qǐng)繼續(xù)關(guān)注腳本之家,需要的朋友可以參考下

Java應(yīng)用程序是運(yùn)行在JVM上的,但是你對(duì)JVM技術(shù)了解嗎?這篇文章(這個(gè)系列的第一部分)講述了經(jīng)典Java虛擬機(jī)是怎么樣工作的,例如:Java一次編寫的利弊,跨平臺(tái)引擎,垃圾回收基礎(chǔ)知識(shí),經(jīng)典的GC算法和編譯優(yōu)化。之后的文章會(huì)講JVM性能優(yōu)化,包括最新的JVM設(shè)計(jì)——支持當(dāng)今高并發(fā)Java應(yīng)用的性能和擴(kuò)展。

如果你是一個(gè)開發(fā)人員,你肯定遇到過這樣的特殊感覺,你突然靈光一現(xiàn),所有的思路連接起來了,你能以一個(gè)新的視角來回想起你以前的想法。我個(gè)人很喜歡學(xué)習(xí)新知識(shí)帶來的這種感覺。我已經(jīng)有過很多次這樣的經(jīng)歷了,在我使用JVM技術(shù)工作時(shí),特別是使用垃圾回收和JVM性能優(yōu)化時(shí)。在這個(gè)新的Java世界中,我希望和你分享我的這些啟發(fā)。希望你能像我寫這篇文章一樣興奮的去了解JVM的性能。

這個(gè)系列文章,是為所有有興趣去學(xué)習(xí)更多JVM底層知識(shí),和JVM實(shí)際做了什么的Java開發(fā)人員所寫的。在更高層次,我將討論垃圾回收和在不影響應(yīng)用運(yùn)行的情況下,對(duì)空閑內(nèi)存安全和速度上的無止境追求。你將學(xué)到JVM的關(guān)鍵部分:垃圾回收和GC算法,編譯優(yōu)化,和一些常用的優(yōu)化。我同樣會(huì)討論為什么Java標(biāo)記這樣難,提供建議什么時(shí)候應(yīng)該考慮測(cè)試性能。最后,我將講一些JVM和GC的新的創(chuàng)新,包括Azul's Zing JVM, IBM JVM, 和Oracle's Garbage First (G1) 垃圾回收中的重點(diǎn)。

我希望你讀完這個(gè)系列時(shí)對(duì)Java可擴(kuò)展性限制的特點(diǎn)有更深的了解,同樣的這樣限制是如何強(qiáng)制我們以最優(yōu)的方式創(chuàng)建一個(gè)Java部署。希望你會(huì)有一種豁然開朗的感受,并且能激發(fā)了一些好的Java靈感:停止接受那些限制,并去改變它!如果你現(xiàn)在還不是一個(gè)開源工作者,這個(gè)系列或許會(huì)鼓勵(lì)你往這方面發(fā)展。

JVM性能和“一次編譯,到處運(yùn)行”的挑戰(zhàn)

我有新的消息告訴那些固執(zhí)的認(rèn)為Java平臺(tái)本質(zhì)上是緩慢的人。當(dāng)Java剛剛做為企業(yè)級(jí)應(yīng)用的時(shí)候,JVM被詬病的Java性能問題已經(jīng)是十幾年前的事了,但這個(gè)結(jié)論,現(xiàn)在已經(jīng)過時(shí)了。這是真的,如果你現(xiàn)在在不同的開發(fā)平臺(tái)上運(yùn)行簡(jiǎn)單靜態(tài)和確定的任務(wù)時(shí),你將很可能發(fā)現(xiàn)使用機(jī)器優(yōu)化過的代碼比使用任何虛擬環(huán)境執(zhí)行的要好,在相同的JVM下。但是,Java的性能在過去10年有了非常大的提升。Java產(chǎn)業(yè)的市場(chǎng)需求和增長(zhǎng),導(dǎo)致了少量的垃圾回收算法、新的編譯創(chuàng)新、和大量的啟發(fā)式方法和優(yōu)化,這些使JVM技術(shù)得到了進(jìn)步。我將在以后的章節(jié)中介紹一些。

JVM的技術(shù)之美,同樣是它最大的挑戰(zhàn):沒有什么可以被認(rèn)為是“一次編譯,到處運(yùn)行”的應(yīng)用。不是優(yōu)化一個(gè)用例,一個(gè)應(yīng)用,一個(gè)特定的用戶負(fù)載,JVM不斷的跟蹤Java應(yīng)用現(xiàn)在在做什么,并進(jìn)行相應(yīng)的優(yōu)化。這種動(dòng)態(tài)的運(yùn)行導(dǎo)致了一系列動(dòng)態(tài)的問題。當(dāng)設(shè)計(jì)創(chuàng)新時(shí)(至少不是在我們向生產(chǎn)環(huán)境要性能時(shí)),致力于JVM的開發(fā)者不會(huì)依賴靜態(tài)編譯和可預(yù)測(cè)的分配率。

JVM性能的事業(yè)

在我早期的工作中我意識(shí)到垃圾回收是非常難“解決”的,我一直著迷于JVMs和中間件技術(shù)。我對(duì)JVMs的熱情開始于我在JRockit團(tuán)隊(duì)中時(shí),編碼一種新的方法用于自學(xué),自己調(diào)試?yán)厥账惴ǎ▍⒖?Resources)。這個(gè)項(xiàng)目(轉(zhuǎn)變?yōu)镴Rockit一個(gè)實(shí)驗(yàn)性的特點(diǎn),并成為Deterministic Garbage Collection算法的基礎(chǔ))開啟了我JVM技術(shù)的旅程。我已經(jīng)在BEA系統(tǒng)、Intel、Sun和Oracle(因?yàn)镺racle收購(gòu)BEA系統(tǒng),所以被Oracle短暫的工作過)工作過。之后我加入了在Azul Systems的團(tuán)隊(duì)去管理Zing JVM,現(xiàn)在我為Cloudera工作。

機(jī)器優(yōu)化的代碼可能會(huì)實(shí)現(xiàn)較好的性能(但這是以犧牲靈活性來做代價(jià)的),但對(duì)于動(dòng)態(tài)裝載和功能快速變化的企業(yè)應(yīng)用這并不是一個(gè)權(quán)衡選擇它的理由。大多數(shù)的企業(yè)為了Java的優(yōu)點(diǎn),更愿意去犧牲機(jī)器優(yōu)化代碼帶來的勉強(qiáng)完美的性能。

1.易于編碼和功能開發(fā)(意義是更短的時(shí)間去回應(yīng)市場(chǎng))
2.得到知識(shí)淵博的的程序員
3.用Java APIs和標(biāo)準(zhǔn)庫(kù)更快速的開發(fā)
4.可移植性——不用為新的平臺(tái)去重新寫Java應(yīng)用

從Java代碼到字節(jié)碼

做為一個(gè)Java程序員,你可能對(duì)編碼、編譯和執(zhí)行Java應(yīng)用很熟悉。例子:我們假設(shè)你有一個(gè)程序(MyApp.java),現(xiàn)在你想讓它運(yùn)行。去執(zhí)行這個(gè)程序你需要先用javac(JDK內(nèi)置的靜態(tài)Java語言到字節(jié)碼編譯器)編譯。基于Java代碼,javac生成相應(yīng)的可執(zhí)行字節(jié)碼,并保存在相同名字的class文件:MyApp.class中。在把Java代碼編譯成字節(jié)碼后,你可以通過java命令(通過命令行或startup腳本,使用不使用startup選項(xiàng)都可以)來啟動(dòng)可執(zhí)行的class文件,從而運(yùn)行你的應(yīng)用。這樣你的class被加載到運(yùn)行時(shí)(意味著Java虛擬機(jī)的運(yùn)行),程序開始執(zhí)行。

這就是表面上每一個(gè)應(yīng)用執(zhí)行的場(chǎng)景,但是現(xiàn)在我們來探究下當(dāng)你執(zhí)行java命令時(shí)究竟發(fā)生了什么。Java虛擬機(jī)是什么?大多數(shù)開發(fā)人員通過持續(xù)調(diào)試來與JVM交互——aka selecting 和value-assigning啟動(dòng)選項(xiàng)能讓你的Java程序跑的更快,同時(shí)避免了臭名昭著的”out of memory”錯(cuò)誤。但是,你是否曾經(jīng)想過,為什么我們起初需要一個(gè)JVM來運(yùn)行Java應(yīng)用呢?

什么是Java虛擬機(jī)?

簡(jiǎn)單的說,一個(gè)JVM是一個(gè)軟件模塊,用于執(zhí)行Java應(yīng)用字節(jié)碼并且把字節(jié)碼轉(zhuǎn)化到硬件,操作系統(tǒng)特殊指令。通過這樣做,JVM允許Java程序在第一次編寫后可以在不同的環(huán)境中執(zhí)行,并不需要更改原始的代碼。Java的可移植性是通往企業(yè)應(yīng)用語言的關(guān)鍵:開發(fā)者并不需要為不同平臺(tái)重寫應(yīng)用代碼,因?yàn)镴VM負(fù)責(zé)翻譯和平臺(tái)優(yōu)化。

一個(gè)JVM基本上是一個(gè)虛擬的執(zhí)行環(huán)境,作為一個(gè)字節(jié)碼指令機(jī)器,而用于分配執(zhí)行任務(wù)和執(zhí)行內(nèi)存操作通過與底層的交互。

一個(gè)JVM同樣為運(yùn)行的Java應(yīng)用照看動(dòng)態(tài)資源管理。這就意味著它掌握分配和釋放內(nèi)存,在每個(gè)平臺(tái)上保持一致的線程模型,在應(yīng)用執(zhí)行的地方用一種適于CPU架構(gòu)的方式組織可執(zhí)行的指令。JVM把開發(fā)人員從跟蹤對(duì)象當(dāng)中的引用,和它們需要在系統(tǒng)中存在多長(zhǎng)時(shí)間中解放出來。同樣的它不用我們管理何時(shí)去釋放內(nèi)存——一個(gè)像C語言那樣的非動(dòng)態(tài)語言的痛點(diǎn)。

你可以把JVM當(dāng)做是一個(gè)專門為Java運(yùn)行的操作系統(tǒng);它的工作是為Java應(yīng)用管理運(yùn)行環(huán)境。一個(gè)JVM基本上是一個(gè)虛擬的通過與底層的交互的執(zhí)行環(huán)境,作為一個(gè)字節(jié)碼指令機(jī)器,而用于分配執(zhí)行任務(wù)和執(zhí)行內(nèi)存操作。

JVM組件概述

有很多寫JVM內(nèi)部和性能優(yōu)化的文章。作為這個(gè)系列的基礎(chǔ),我將會(huì)總結(jié)概述下JVM組件。這個(gè)簡(jiǎn)短的閱覽會(huì)為剛接觸JVM的開發(fā)者有特殊的幫助,會(huì)讓你更想了解之后更深入的討論。

從一種語言到另一種——關(guān)于Java編譯器

編譯器是把一種語言輸入,然后輸出另一種可執(zhí)行的語句。Java編譯器有兩個(gè)主要任務(wù):

1. 讓Java語言更加輕便,不用在第一次寫的時(shí)候固定在特定的平臺(tái);

2. 確保對(duì)特定的平臺(tái)產(chǎn)生有效的可執(zhí)行的代碼。

編譯器可以是靜態(tài)也可以是動(dòng)態(tài)。一個(gè)靜態(tài)編譯的例子是javac。它把Java代碼當(dāng)做輸入,并轉(zhuǎn)化為字節(jié)碼(一種在Java虛擬機(jī)執(zhí)行的語言)。靜態(tài)編譯器一次解釋輸入的代碼,輸出可執(zhí)行的形式,這個(gè)是在程序執(zhí)行時(shí)將被用到。因?yàn)檩斎胧庆o態(tài)的,你將總能看到結(jié)果相同。只有當(dāng)你修改原始代碼并重新編譯時(shí),你才能看到不同的輸出。

動(dòng)態(tài)編譯器,例如Just-In-Time (JIT)編譯器,把一種語言動(dòng)態(tài)的轉(zhuǎn)化為另一種,這意味著它們做這些時(shí)把代碼被執(zhí)行。JIT編譯器讓你收集或創(chuàng)建運(yùn)行數(shù)據(jù)分析(通過插入性能計(jì)數(shù)的方式),用編譯器決定,用手邊的環(huán)境數(shù)據(jù)。動(dòng)態(tài)的編譯器可以在編譯成語言的過程之中,實(shí)現(xiàn)更好的指令序列,把一系列的指令替換成更有效的,甚至消除多余的操作。隨著時(shí)間的增長(zhǎng)你將收集更多的代碼配制數(shù)據(jù),做更多更好的編譯決定;整個(gè)過程就是我們通常稱為的代碼優(yōu)化和重編譯。

動(dòng)態(tài)編譯給了你可以根據(jù)行為去調(diào)整動(dòng)態(tài)的變化的優(yōu)勢(shì),或隨著應(yīng)用裝載次數(shù)的增加催生的新的優(yōu)化。這就是為什么動(dòng)態(tài)編譯器非常適合Java運(yùn)行。值得注意的是,動(dòng)態(tài)編譯器請(qǐng)求外部數(shù)據(jù)結(jié)構(gòu),線程資源,CPU周期分析和優(yōu)化。越深層次的優(yōu)化,你將需要越多的資源。然而在大多數(shù)環(huán)境中,頂層對(duì)執(zhí)行性能的提升幫助非常小——比你純粹的解釋要快5到10倍的性能。

分配會(huì)導(dǎo)致垃圾回收

分配在每一個(gè)線程基于每個(gè)“Java進(jìn)程分配內(nèi)存地址空間”,或者叫Java堆,或者直接叫堆。在Java世界中單線程分配在客戶端應(yīng)用程序中很常見。然而,單線程分配在企業(yè)應(yīng)用和工作裝載服務(wù)端變的沒有任何益處,因?yàn)樗]有使用現(xiàn)在多核環(huán)境的并行優(yōu)勢(shì)。

并行應(yīng)用設(shè)計(jì)同樣迫使JVM保證在同一時(shí)間,多線程不會(huì)分配同一個(gè)地址空間。你可以通過在整個(gè)分配空間中放把鎖來控制。但這種技術(shù)(通常叫做堆鎖)很消耗性能,持有或排隊(duì)線程會(huì)影響資源利用和應(yīng)用優(yōu)化的性能。多核系統(tǒng)好的一面是,它們創(chuàng)造了一個(gè)需求,為各種各樣的新的方法在資源分配的同時(shí)去阻止單線程的瓶頸,和序列化。

一個(gè)常用的方法是把堆分成幾部分,在對(duì)應(yīng)用來說每個(gè)合式分區(qū)大小的地方——顯然它們需要調(diào)優(yōu),分配率和對(duì)象大小對(duì)不同應(yīng)用來說有顯著的變化,同樣線程的數(shù)量也不同。線程本地分配緩存(Thread Local Allocation Buffer,簡(jiǎn)寫:TLAB),或者有時(shí),線程本地空間(Thread Local Area,簡(jiǎn)寫:TLA),是一個(gè)專門的分區(qū),在其中線程不用聲明一個(gè)全堆鎖就可以自由分配。當(dāng)區(qū)域滿的時(shí)候,堆就滿了,表示堆上的空閑空間不夠用來放對(duì)象的,需要分配空間。當(dāng)堆滿的時(shí)候,垃圾回收就會(huì)開始。

碎片

使用TLABs捕獲異常,是把堆碎片化來降低內(nèi)存效率。如果一個(gè)應(yīng)用在要分配對(duì)象時(shí)正巧不能增加或者不能完全分配一個(gè)TLAB空間,這將會(huì)有空間太小而不能生成新對(duì)象的風(fēng)險(xiǎn)。這樣的空閑空間被當(dāng)做“碎片”。如果應(yīng)用程序一直保持對(duì)象的引用,然后再用剩下的空間分配,最后這些空間會(huì)在很長(zhǎng)一段時(shí)間內(nèi)空閑。

碎片就是當(dāng)碎片被分散在堆中的時(shí)候——通過一小段不用的內(nèi)存空間來浪費(fèi)堆空間。為你的應(yīng)用分配 “錯(cuò)誤的”TLAB空間(關(guān)于對(duì)象的大小、混合對(duì)象的大小和引用持有率)是導(dǎo)致堆內(nèi)碎片增多的原因。在隨著應(yīng)用的運(yùn)行,碎片的數(shù)量會(huì)增加在堆中占有的空間。碎片導(dǎo)致性能下降,系統(tǒng)不能給新應(yīng)用分配足夠的線程和對(duì)象。垃圾回收器在隨后會(huì)很難阻止out-of-memory異常。

TLAB浪費(fèi)在工作中產(chǎn)生。一種方法可以完全或暫時(shí)避免碎片,那就是在每次基礎(chǔ)操作時(shí)優(yōu)化TLAB空間。這種方法典型的作法是應(yīng)用只要有分配行為,就需要重新調(diào)優(yōu)。通過復(fù)雜的JVM算法可以實(shí)現(xiàn),另一種方法是組織堆分區(qū)實(shí)現(xiàn)更有效的內(nèi)存分配。例如,JVM可以實(shí)現(xiàn)free-lists,它是連接起一串特定大小的空閑內(nèi)存塊。一個(gè)連續(xù)的空閑內(nèi)存塊和另一個(gè)相同大小的連續(xù)內(nèi)存塊相連,這樣會(huì)創(chuàng)建少量的鏈表,每個(gè)都有自己的邊界。在有些情況下free-lists導(dǎo)致更好的合適內(nèi)存分配。線程可以對(duì)象分配在一個(gè)差不多大小的塊中,這樣比你只依靠固定大小的TLAB,潛在的產(chǎn)生少的碎片。

GC瑣事

有一些早期的垃圾收集器擁有多個(gè)老年代,但是當(dāng)超過兩個(gè)老年代的時(shí)候會(huì)導(dǎo)致開銷超過價(jià)值。另一種優(yōu)化分配減少碎片的方法,就是創(chuàng)造所謂的新生代,這是一個(gè)專門用于分配新對(duì)象的專用堆空間。剩余的堆會(huì)成為所謂的老年代。老年代是用來分配長(zhǎng)時(shí)間存在的對(duì)象的,被假定會(huì)存在很長(zhǎng)時(shí)間的對(duì)象包括不被垃圾收集的對(duì)象或者大對(duì)象。為了更好的理解這種分配的方法,我們需要講一些垃圾收集的知識(shí)。

垃圾回收和應(yīng)用性能

垃圾回收是JVM的垃圾回收器去釋放沒有引用的被占據(jù)的堆內(nèi)存。當(dāng)?shù)谝淮斡|發(fā)垃圾收集時(shí),所有的對(duì)象引用還被保存著,被以前的引用占據(jù)的空間被釋放或重新分配。當(dāng)所有可回收的內(nèi)存被收集后,空間等待被抓取和再次分配給新對(duì)象。

垃圾回收器永遠(yuǎn)都不能重聲明一個(gè)引用對(duì)象,這樣做會(huì)破壞JVM的標(biāo)準(zhǔn)規(guī)范。這個(gè)規(guī)則的異常是一個(gè)可以捕獲的soft或weak引用 ,如果垃圾收集器將要將近耗盡內(nèi)存。我強(qiáng)烈推薦你盡量避免weak引用,然而,因?yàn)镴ava規(guī)范的模糊導(dǎo)致了錯(cuò)誤的解釋和使用的錯(cuò)誤。更何況,Java是被設(shè)計(jì)為動(dòng)態(tài)內(nèi)存管理,因?yàn)槟悴恍枰紤]什么時(shí)候和什么地方釋放內(nèi)存。

垃圾收集器的一個(gè)挑戰(zhàn)是在分配內(nèi)存時(shí),需要盡量不影響運(yùn)行著的應(yīng)用。如果你不盡量垃圾收集,你的應(yīng)用將耗近內(nèi)存;如果你收集的太頻繁,你將損失吞吐量和響應(yīng)時(shí)間,這將對(duì)運(yùn)行的應(yīng)用產(chǎn)生壞的影響。

GC算法

有許多不同的垃圾回收算法。稍后,在這個(gè)系列里將深入討論幾點(diǎn)。在最高層,垃圾收集兩個(gè)最主要的方法是引用計(jì)數(shù)和跟蹤收集器。

引用計(jì)數(shù)收集器會(huì)跟蹤一個(gè)對(duì)象指向多少個(gè)引用。當(dāng)一個(gè)對(duì)象的引用為0時(shí),內(nèi)存將被立即回收,這是這種方法的優(yōu)點(diǎn)之一。引用計(jì)數(shù)方法的難點(diǎn)在于環(huán)形數(shù)據(jù)結(jié)構(gòu)和保持所有的引用即時(shí)更新。

跟蹤收集器對(duì)仍在引用的對(duì)象標(biāo)記,用已經(jīng)標(biāo)記的對(duì)象,反復(fù)的跟隨和標(biāo)記所有的引用對(duì)象。當(dāng)所有的仍然引用的對(duì)象被標(biāo)記為“live”時(shí),所有的不被標(biāo)記的空間將被回收。這種方法管理環(huán)形數(shù)據(jù)結(jié)構(gòu),但是在很多情況下收集器應(yīng)該等待直到所有標(biāo)記完成,在重新回收不被引用的內(nèi)存之前。

有不種的途徑來被上面的方法。最著名的算法是 marking 或copying 算法, parallel 或 concurrent算法。我將在稍后的文章中討論這些。

通常來說垃圾回收的意義是致力于在堆中給新對(duì)象和老對(duì)象分配地址空間。其中“老對(duì)象”是指在許多垃圾回收后幸存的對(duì)象。用新生代來給新對(duì)象分配,老年代給老對(duì)象,這樣能通過快速回收占據(jù)內(nèi)存的短時(shí)間對(duì)象來減少碎片,同樣通過把長(zhǎng)時(shí)間存在的對(duì)象聚合在一起,并把它們放到老年代地址空間中。所有這些在長(zhǎng)時(shí)間對(duì)象和保存堆內(nèi)存不碎片化之間減少了碎片。新生代的一個(gè)積極作用是延遲了需要花費(fèi)更大代價(jià)回收老年代對(duì)象的時(shí)間,你可以為短暫的對(duì)象重復(fù)利用相同的空間。(老空間的收集會(huì)花費(fèi)更多,是因?yàn)殚L(zhǎng)時(shí)間存在的對(duì)象們,會(huì)包含更多的引用,需要更多的遍歷。)

最后值的一提的算法是compaction,這是管理內(nèi)存碎片的方法。Compaction基本來說就是把對(duì)象移動(dòng)到一起,從來釋放更大的連續(xù)內(nèi)存空間。如果你熟悉磁盤碎片和處理它的工具,你會(huì)發(fā)現(xiàn)compaction跟它很像,不同的是這個(gè)運(yùn)行在Java堆內(nèi)存中。我將在系列中詳細(xì)討論compaction。

總結(jié):回顧和重點(diǎn)

JVM允許可移植(一次編程,到處運(yùn)行)和動(dòng)態(tài)的內(nèi)存管理,所有Java平臺(tái)的主要特性,都是它受歡迎和提高生產(chǎn)力的原因。

在第一篇JVM性能優(yōu)化系統(tǒng)的文章中我解釋了一個(gè)編譯器怎么把字節(jié)碼轉(zhuǎn)化為目標(biāo)平臺(tái)的指令語言的,并幫助動(dòng)態(tài)的優(yōu)化Java程序的執(zhí)行。不同的應(yīng)用需要不同的編譯器。

我同樣簡(jiǎn)述了內(nèi)存分配和垃圾收集,和這些怎么與Java應(yīng)用性能相關(guān)的。基本上,你越快的填滿堆和頻繁的觸發(fā)垃圾收集,Java應(yīng)用的占有率越高。垃圾收集器的一個(gè)挑戰(zhàn)是在分配內(nèi)存時(shí),需要盡量不影響運(yùn)行著的應(yīng)用,但要在應(yīng)用耗盡內(nèi)存之前。在以后的文章中我們會(huì)更詳細(xì)的討論傳統(tǒng)的和新的垃圾回收和JVM性能優(yōu)化。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 处女私拍 | 欧美日本一本线在线观看 | 国产欧美在线播放 | 二次元美女挤奶漫画 | 国产九九视频在线观看 | 久久99精品国产免费观看 | 精品视频在线免费播放 | 国产一区二区免费福利片 | 国产东北三老头伦一肥婆 | 顶级欧美做受xxx000大乳 | 亚洲欧美一级夜夜爽w | 500av导航大全精品 | 日本免费观看95视频网站 | 99超级碰碰成人香蕉网 | 国产99视频精品免费视频免里 | 精品湿 | 色综合久久丁香婷婷 | 纲手被强喷水羞羞漫画 | 亚洲天堂影视 | 欧美日韩国产亚洲一区二区三区 | 超级乱淫伦小说全集np | 陈峰姚瑶全集小说无删节 | 2019亚洲男人天堂 | 乌克兰17一18处交 | 免费国产白棉袜踩踏区域 | 三极片在线观看 | 亚洲欧美日韩特级毛片 | 女人爽到喷水的视频免费 | 操老逼| 憋尿调教绝望之岛 | 久久亚洲一级α片 | hd在线观看免费高清视频 | 无套日出白浆在线播放 | 91热国内精品永久免费观看 | 国产未成女年一区二区 | 欧美在线看片a免费观看 | 亚洲首页国产精品丝袜 | 白丝美女用胸伺候主人 | 黑人k8经典 | 操乳 | 久久一本综合 |