亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android性能優化系列之內存優化

2019-11-09 18:31:42
字體:
來源:轉載
供稿:網友

原文地址:http://blog.csdn.net/u012124438/article/details/54647287

java中,內存的分配是由程序完成的,而內存的釋放是由垃圾收集器(Garbage Collection,GC)完成的,程序員不需要通過調用函數來釋放內存,但也隨之帶來了內存泄漏的可能,上篇博客,我介紹了 Android性能優化系列之布局優化,本篇博客,我將介紹內存優化的相關知識。

內存的分配策略概述

程序運行時的內存分配有三種策略,分別是靜態的,棧式的,和堆式的,對應的,三種存儲策略使用的內存空間主要分別是靜態存儲區(也稱方法區)、堆區和棧區。

靜態存儲區(方法區):內存在程序編譯的時候就已經分配好,這塊內存在程序整個運行期間都存在。它主要存放靜態數據、全局static數據和常量。

棧區:在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。

堆區:亦稱動態內存分配。程序在運行的時候用malloc或new申請任意大小的內存,程序員自己負責在適當的時候用free或delete釋放內存(Java則依賴垃圾回收器)。動態內存的生存期可以由我們決定,如果我們不釋放內存,程序將在最后才釋放掉動態內存。 但是,良好的編程習慣是:如果某動態內存不再使用,需要將其釋放掉。

堆和棧的區別: 在函數中(說明是局部變量)定義的一些基本類型的變量和對象的引用變量都是在函數的棧內存中分配。當在一段代碼塊中定義一個變量時,java就在棧中為這個變量分配內存空間,當超過變量的作用域后,java會自動釋放掉為該變量分配的內存空間,該內存空間可以立刻被另作他用。

堆內存用于存放所有由new創建的對象(內容包括該對象其中的所有成員變量)和數組。在堆中分配的內存,由java虛擬機自動垃圾回收器來管理。在堆中產生了一個數組或者對象后,還可以在棧中定義一個特殊的變量,這個變量的取值等于數組或者對象在堆內存中的首地址,在棧中的這個特殊的變量就變成了數組或者對象的引用變量,以后就可以在程序中使用棧內存中的引用變量來訪問堆中的數組或者對象,引用變量相當于為數組或者對象起的一個別名,或者代號

堆是不連續的內存區域(因為系統是用鏈表來存儲空閑內存地址,自然不是連續的),堆大小受限于計算機系統中有效的虛擬內存(32bit系統理論上是4G),所以堆的空間比較靈活,比較大。棧是一塊連續的內存區域,大小是操作系統預定好的,windows下棧大小是2M(也有是1M,在編譯時確定,VC中可設置)。

對于堆,頻繁的new/delete會造成大量內存碎片,使程序效率降低。對于棧,它是先進后出的隊列,進出一一對應,不產生碎片,運行效率穩定高。 這里寫圖片描述

所以我們可以得出結論: 1.局部變量的基本數據類型和引用存儲于棧中,引用的對象實體存儲于堆中。因為它們屬于方法中的變量,生命周期隨方法而結束。

2.成員變量全部存儲與堆中(包括基本數據類型,引用和引用的對象實體),因為它們屬于類,類對象終究是要被new出來使用的。

3.我們所說的內存泄露,只針對堆內存,他們存放的就是引用指向的對象實體。

內存泄露產生的原因

在Java中,內存的分配是由程序完成的,而內存的釋放是由垃圾收集器(Garbage Collection,GC)完成的,程序員不需要通過調用函數來釋放內存,但它只能回收無用并且不再被其它對象引用的那些對象所占用的空間。

Java的內存垃圾回收機制是從程序的主要運行對象(如靜態對象/寄存器/棧上指向的堆內存對象等)開始檢查引用鏈,當遍歷一遍后得到上述這些無法回收的對象和他們所引用的對象鏈,組成無法回收的對象集合,而其他孤立對象(集)就作為垃圾回收。GC為了能夠正確釋放對象,必須監控每一個對象的運行狀態,包括對象的申請、引用、被引用、賦值等,GC都需要進行監控。監視對象狀態是為了更加準確地、及時地釋放對象,而釋放對象的根本原則就是該對象不再被引用。

在Java中,這些無用的對象都由GC負責回收,因此程序員不需要考慮這部分的內存泄露。雖然,我們有幾個函數可以訪問GC,例如運行GC的函數System.gc(),但是根據Java語言規范定義,該函數不保證JVM的垃圾收集器一定會執行。因為不同的JVM實現者可能使用不同的算法管理GC。通常GC的線程的優先級別較低。JVM調用GC的策略也有很多種,有的是內存使用到達一定程度時,GC才開始工作,也有定時執行的,有的是平緩執行GC,有的是中斷式執行GC。但通常來說,我們不需要關心這些。

但是我們仍然可以去監聽系統的GC過程,以此來分析我們應用程序當前的內存狀態。那么怎樣才能去監聽系統的GC過程呢?其實非常簡單,系統每進行一次GC操作時,都會在LogCat中打印一條日志,我們只要去分析這條日志就可以了,日志的基本格式如下所示:

1.D/dalvikvm: <GC_Reason> <Amount_freed>, <Heap_stats>, <Pause_time> 11

首先第一部分GC_Reason,這個是觸發這次GC操作的原因,一般情況下一共有以下幾種觸發GC操作的原因: GC_CONCURRENT: 當我們應用程序的堆內存快要滿的時候,系統會自動觸發GC操作來釋放內存。

GC_FOR_MALLOC: 當我們的應用程序需要分配更多內存,可是現有內存已經不足的時候,系統會進行GC操作來釋放內存。GC_HPROF_DUMP_HEAP: 當生成HPROF文件的時候,系統會進行GC操作,關于HPROF文件我們下面會講到。 GC_EXPLICIT: 這種情況就是我們剛才提到過的,主動通知系統去進行GC操作,比如調用System.gc()方法來通知系統?;蛘咴贒DMS中,通過工具按鈕也是可以顯式地告訴系統進行GC操作的。

接下來第二部分Amount_freed,表示系統通過這次GC操作釋放了多少內存。

然后Heap_stats中會顯示當前內存的空閑比例以及使用情況(活動對象所占內存 / 當前程序總內存)。

最后Pause_time表示這次GC操作導致應用程序暫停的時間。關于這個暫停的時間,Android在2.3的版本當中進行過一次優化,在2.3之前GC操作是不能并發進行的,也就是系統正在進行GC,那么應用程序就只能阻塞住等待GC結束。雖說這個阻塞的過程并不會很長,也就是幾百毫秒,但是用戶在使用我們的程序時還是有可能會感覺到略微的卡頓。而自2.3之后,GC操作改成了并發的方式進行,就是說GC的過程中不會影響到應用程序的正常運行,但是在GC操作的開始和結束的時候會短暫阻塞一段時間,不過優化到這種程度,用戶已經是完全無法察覺到了。

我們來看看Java中需要被回收的垃圾:

{Person p1 = new Person();……}

引用句柄p1的作用域是從定義到“}”處,執行完這對大括號中的所有代碼后,產生的Person對象就會變成垃圾,因為引用這個對象的句柄p1已超過其作用域,p1失效,在棧中被銷毀,因此堆上的Person對象不再被任何句柄引用了。 因此person變為垃圾,會被回收。

這里我們需要講述一個關鍵詞:引用,通過A能調用并訪問到B,那就說明A持有B的引用,或A就是B的引用,B的引用計數+1.

(1)比如 Person p1 = new Person();通過P1能操作Person對象,因此P1是Person的引用; (2)比如類O中有一個成員變量是I類對象,因此我們可以使用o.i的方式來訪問I類對象的成員,因此o持有一個i對象的引用。

GC過程與對象的引用類型是嚴重相關的,我們來看看Java對引用的分類Strong reference, SoftReference, WeakReference, PhatomReference

這里寫圖片描述

在Android應用的開發中,為了防止內存溢出,在處理一些占用內存大而且聲明周期較長的對象時候,可以盡量應用軟引用和弱引用技術。

軟/弱引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。利用這個隊列可以得知被回收的軟/弱引用的對象列表,從而為緩沖器清除已失效的軟/弱引用。

假設我們的應用會用到大量的默認圖片,比如應用中有默認的頭像,默認游戲圖標等等,這些圖片很多地方會用到。如果每次都去讀取圖片,由于讀取文件需要硬件操作,速度較慢,會導致性能較低。所以我們考慮將圖片緩存起來,需要的時候直接從內存中讀取。但是,由于圖片占用內存空間比較大,緩存很多圖片需要很多的內存,就可能比較容易發生OutOfMemory異常。這時,我們可以考慮使用軟/弱引用技術來避免這個問題發生。以下就是高速緩沖器的雛形:

首先定義一個HashMap,保存軟引用對象。

1.private Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>();

再來定義一個方法,保存Bitmap的軟引用到HashMap

public class CacheSoftRef { //首先定義一個HashMap,保存引用對象 private Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>(); //再來定義一個方法,保存Bitmap的軟引用到HashMap public void addBitmapToCache(String path) { //強引用的Bitmap對象 Bitmap bitmap = BitmapFactory.decodeFile(path); //軟引用的Bitmap對象 SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap); //添加該對象到Map中使其緩存 imageCache.put(path, softBitmap); } //獲取的時候,可以通過SoftReference的get()方法得到Bitmap對象 public Bitmap getBitmapByPath(String path) { //從緩存中取軟引用的Bitmap對象 SoftReference<Bitmap> softBitmap = imageCache.get(path); //判斷是否存在軟引用 if (softBitmap == null) { return null; } //通過軟引用取出Bitmap對象,如果由于內存不足Bitmap被回收,將取得空,如果未被回收, //則可重復使用,提高速度。 Bitmap bitmap = softBitmap.get(); return bitmap; }}

使用軟引用以后,在OutOfMemory異常發生之前,這些緩存的圖片資源的內存空間可以被釋放掉的,從而避免內存達到上限,避免Crash發生。

如果只是想避免OutOfMemory異常的發生,則可以使用軟引用。如果對于應用的性能更在意,想盡快回收一些占用內存比較大的對象,則可以使用弱引用。

另外可以根據對象是否經常使用來判斷選擇軟引用還是弱引用。如果該對象可能會經常使用的,就盡量用軟引用。如果該對象不被使用的可能性更大些,就可以用弱引用。

所以我們得出內存泄漏的原因:堆內存中的長生命周期的對象持有短生命周期對象的強/軟引用,盡管短生命周期對象已經不再需要,但是因為長生命周期對象持有它的引用而導致不能被回收,這就是Java中內存泄露的根本原因。

內存泄漏的檢測

說了那么多關于內存分配的知識,接下來我們就看看Android給我們提供了哪些工具來解決內存泄漏的問題

Allocation Tracker(Device Monitor)

Allocation Tracker位于Android Device Monitor中 這里寫圖片描述

Allocation Tracker面板 這里寫圖片描述

各名稱的含義如下: 這里寫圖片描述

Allocation Tracker操作 1.首先進入你要追蹤的界面 2.點擊Start Tracking按鈕,開始跟蹤內存分配軌跡 3.操作你的界面,盡量時間短點 4.點擊Get Allocations按鈕,抓去內存分配軌跡信息,顯示在右邊的面板中,默認以內存大小排序,你可以以分配順序排序或者仍以列排序。 5.logcat中會顯示出這次的軌跡共抓到內存分配軌跡記錄數,可以簡單的理解分配了多少次內存,這個數值和Alloc order的最大值是相等的 6.如果你不想看那么多亂七八糟的,你可以使用Filter來過濾,輸入包名就可以了。

跟蹤內存軌跡 如果這個時候我們想單獨獲取某次操作的內存軌跡,首先一定要記得Stop Tracking再Start Tracking一下,讓追蹤點初始化一下,然后就進行我們需要觀察內存變化的操作,然后點擊Get Allocations,這個時候我們從首頁進入一個詳情頁,看一下我們的內存分配軌跡:這里寫圖片描述

追蹤到的內存分配20293次,看著是不是有點無從下手,沒關系,用Filter過濾下: 這里寫圖片描述

過濾后,就剩下了跟我們App源碼有關系的分配軌跡,我們隨便選擇一欄,可以看到其trace信息: 這里寫圖片描述

上圖中,我們可以看出來,在第635次內存分配中,分配的是IntroduceFragment對象,占用內存224字節,處理線程Id為3245,在java.lang.Class的newInstance方法中分配的。從trace信息可以看出來該方法一步一步被調用的信息。

DDMS的Heap Viewer

Heap Viewer能做什么? 實時查看App分配的內存大小和空閑內存大小 發現Memory Leaks

在Devices 中,點擊要監控的程序。 點擊Devices視圖界面中最上方一排圖標中的“Update Heap” 點擊Heap視圖 點擊Heap視圖中的“Cause GC”按鈕 到此為止需檢測的進程就可以被監視。 這里寫圖片描述

按上圖的標記順序按下,我們就能看到內存的具體數據,右邊面板中數值會在每次GC時發生改變,包括App自動觸發或者你來手動觸發。 ok,現在來解釋下面板中的名詞

總覽 這里寫圖片描述

這里寫圖片描述

詳情 這里寫圖片描述

這里寫圖片描述

下面是每一個對象都有的列名含義: 這里寫圖片描述

當我們點擊某一行時,可以看到如下的柱狀圖: 這里寫圖片描述

橫坐標是對象的內存大小,這些值隨著不同對象是不同的,縱坐標是在某個內存大小上的對象的數量

Heap Viewer的使用 我們說Heap Viewer適合發現內存泄漏的問題,那么如何檢測呢? 那么如何檢測呢? 進入某應用,不斷的操作該應用,同時注意觀察data object的Total Size值,正常情況下Total Size值都會穩定在一個有限的范圍內,也就是說由于程序中的的代碼良好,沒有造成對象不被垃圾回收的情況。

所以說雖然我們不斷的操作會不斷的生成很多對象,而在虛擬機不斷的進行GC的過程中,這些對象都被回收了,內存占用量會會落到一個穩定的水平;反之如果代碼中存在沒有釋放對象引用的情況,則data object的Total Size值在每次GC后不會有明顯的回落。隨著操作次數的增多Total Size的值會越來越大,直到到達一個上限后導致進程被殺掉。

MAT工具

那么通過上面DDMS工具,現在我們已經可以比較輕松地發現應用程序中是否存在內存泄露的現象了。 我們應該怎么定位到具體是哪里出的內存泄露呢?這就需要借助一個內存分析工具了,叫做Eclipse Memory Analyzer(MAT)。下載地址是:http://eclipse.org/mat/downloads.php。為了使用該工具,我們需要hprof文件。但是該文件不能直接被MAT使用,需要進行一步轉化,可以使用hprof-conv命令來轉化,但是Android Studio可以直接轉化,轉化方法如下:

1.選擇一個hprof文件,點擊右鍵選擇Export to standard .hprof選項。 這里寫圖片描述

2.填寫更改后的文件名和路徑: 這里寫圖片描述

點擊OK按鈕后,MAT工具所需的文件就生成了,下面我們用MAT來打開該工具: 1.打開MAT后選擇File->Open File選擇我們剛才生成的doctorq.hprof文件 2.選擇該文件后,MAT會有幾秒種的時間解析該文件,有的hprof文件可能過大,會有更長的時間解析,解析后,展現在我們的面前的界面如下:

這里寫圖片描述

上圖最中央的那個餅狀圖展示了最大的幾個對象所占內存的比例,這張圖中提供的內容并不多,我們可以忽略它。在這個餅狀圖的下方就有幾個非常有用的工具了,我們來學習一下。

Histogram可以列出內存中每個對象的名字、數量以及大小。 Dominator Tree會將所有內存中的對象按大小進行排序,并且我們可以分析對象之間的引用結構。 現在點擊Dominator Tree,結果如下圖所示:

這里寫圖片描述

首先Retained Heap表示這個對象以及它所持有的其它引用(包括直接和間接)所占的總內存,因此從上圖中看,前兩行的Retained Heap是最大的,我們分析內存泄漏時,內存最大的對象也是最應該去懷疑的。

在每一行的最左邊都有一個文件型的圖標,這些圖標有的左下角帶有一個點,有的則沒有。帶點的對象就表示是可以被GC Roots訪問到的,可以被GC Root訪問到的對象都是無法被回收的。那么這就說明所有帶紅色的對象都是泄漏的對象嗎?當然不是,因為有些對象系統需要一直使用,本來就不應該被回收。我們可以注意到,上圖當中所有帶點的對象最右邊都有寫一個System Class,說明這是一個由系統管理的對象,并不是由我們自己創建并導致內存泄漏的對象。

上圖當中,除了帶有System Class的行之外,最大的就是第二行的Bitmap對象了,雖然Bitmap對象現在不能被GC Roots訪問到,但不代表著Bitmap所持有的其它引用也不會被GC Roots訪問到?,F在我們可以對著第二行點擊右鍵 -> Path to GC Roots -> exclude weak references,為什么選擇exclude weak references呢?因為弱引用是不會阻止對象被垃圾回收器回收的,所以我們這里直接把它排除掉可以看到,Bitmap對象經過層層引用之后,到了MainActivityLeakClass這個對象,然后在圖標的左下角有個點,就說明在這里可以被GCRoots訪問到了,并且這是由我們自己創建的Thread,并不是SystemClass了,那么由于MainActivityLeakClass能被GC Roots訪問到導致不能被回收,導致它所持有的其它引用也無法被回收了,包括MainActivity,也包括MainActivity中所包含的圖片。

通過這種方式,我們就成功地將內存泄漏的原因找出來了。

Histogram的用法 用的最多的功能是 Histogram,點擊 Actions下的 Histogram項將得到 Histogram結果: 這里寫圖片描述

它按類名將所有的實例對象列出來,可以點擊表頭進行排序,在表的第一行可以輸入正則表達式來匹配結果 : 這里寫圖片描述

在某一項上右鍵打開菜單選擇 list objects ->with incoming refs 將列出該類的實例: 這里寫圖片描述

它展示了對象間的引用關系,比如展開后的第一個子項表示這個 HomePage(0x420ca5b0)被HomePageContainer(0x420c9e40)中的 mHomePage屬性所引用.快速找出某個實例沒被釋放的原因,可以右健 Path to GC Roots–>exclue all phantom/weak/soft etc. reference :這里寫圖片描述得到的結果是: 這里寫圖片描述從表中可以看出 PreferenceManager -> … ->HomePage這條線路就引用著這個 HomePage實例。用這個方法可以快速找到某個對象的 GC Root,一個存在 GC Root的對象是不會被 GC回收掉的.

Histogram 對比

為查找內存泄漏,通常需要兩個 Dump結果作對比,打開 Navigator History面板,將兩個表的 Histogram結果都添加到 Compare Basket中去 :

這里寫圖片描述

添加好后,打開 Compare Basket面板,得到結果: 這里寫圖片描述

點擊右上角的 ! 按鈕,將得到比對結果: 這里寫圖片描述注意,上面這個對比結果不利于查找差異,可以調整對比選項: 這里寫圖片描述

再把對比的結果排序,就可得到直觀的對比結果: 這里寫圖片描述

也可以對比兩個對象集合,方法與此類似,都是將兩個 Dump結果中的對象集合添加到Compare Basket中去對比。找出差異后用 Histogram查詢的方法找出 GC Root,定位到具體的某個對象上。

LeakCanary

有別于MAT和AndroidStudio中Monitors的實時內存占用圖,使用LeakCanary分析內存泄露就簡單多了LeakCanary是Square開源了一個內存泄露自動探測神器 。這是項目的github倉庫地址:https://github.com/square/leakcanary 。使用非常簡單,在build.gradle中引入包依賴:

debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'在application中的onCreate方法中增加初始化代碼:if (LeakCanary.isInAnalyzerProcess(this)) { // This process is dedicated to LeakCanary for // heap analysis. // You should not init your app in this process. return;}LeakCanary.install(this);

集成后什么都不用做,按照正常測試,當有內存泄漏發生后,應用會通過系統通知欄發出通知,點擊通知就可以進入查看內存泄漏的具體信息。在這里舉個實踐中的例子。把LeakCanary集成到項目中后,等App啟動后一會,系統通知到了,點擊通知,跳轉到泄漏的詳情頁面進行查看:

這里寫圖片描述

很明顯,WebSiteQueryActivity泄露了。首先,static 的MaskHeadView.fLayout變量引用了FrameLayout.mContext對象,這個對象的引用就是指向了WebSiteQueryActivity的實例,導致了它的泄漏,在第二節中我們說過static對象是內部的static對象是比較容易造成內存泄漏的,檢查代碼發現,MaskHeadView直接在WebSiteQueryActivity的xml文件中使用了,因此持有WebSiteQueryActivity的實例,因為fLayout對象是靜態的,因此它的生命周期與Application同樣長,因此WebSiteQueryActivity退出后,它的實例引用依然被fLayout持有,導致它無法被回收從而內存泄露了。仔細檢查代碼,發現fLayout并沒有被外部使用到,應該是之前的開發者手抖加了個static字段上去或者是現在不用了,但是沒有去掉,在這里我直接去掉了這個修飾符,在此build代碼,這個內存泄漏的現象消失了。

//去掉static修飾符,避免static對象引起的內存泄漏private static FrameLayout fLayout;public MaskHeadView(Context context, AttributeSet attrs) { super(context, attrs); this.context=context; initView(context);}private void initView(Context context2) { view = LayoutInflater.from(context).inflate(R.layout. mask_head_view, this); fLayout=(FrameLayout) view.findViewById(R.id. mask_container);}

這只是個極簡單的例子,但方法是一樣的。順便提一句,其實無論是MAT工具的內存分析,還是AndroidStudio中自帶的分析工具亦或是LeakCanary,原理都是一樣的,都是dumpJava heap出來進行分析,找到泄漏的問題,只是LeakCanary幫我們把分析的工作做了。但值得一提的是,LeakCanary并不是萬能的,有些內存泄漏,它也無法檢測出來。

好了,關于內存泄露的相關內容就介紹到這,關于一些可能導致內存泄漏的原因,可以參考我的另外一篇博客Android中常見的內存泄露


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲国产成人久久综合一区| 91福利视频在线观看| 亚洲人成在线观看网站高清| 久久人体大胆视频| 久久久久久网址| 成人写真福利网| 国产成人精品久久二区二区| 久久精品国产视频| 国产精品中文字幕在线| 欧美另类老女人| 国产99久久精品一区二区 夜夜躁日日躁| 国产精品视频午夜| 日韩高清av一区二区三区| 亚洲欧美三级在线| 黑人巨大精品欧美一区二区一视频| 国产成人av在线| 色yeye香蕉凹凸一区二区av| 中文字幕亚洲一区二区三区| 日本乱人伦a精品| 91精品一区二区| 国产一区二区三区精品久久久| 久久精品2019中文字幕| 国产精品视频26uuu| 国产一区二区动漫| 欧美午夜宅男影院在线观看| 俺去亚洲欧洲欧美日韩| 亚洲欧美激情四射在线日| 久久成人精品视频| 欧美大片网站在线观看| 国产成人自拍视频在线观看| 久久欧美在线电影| 欧美国产日韩二区| 成人午夜一级二级三级| 免费不卡欧美自拍视频| 国产精品高精视频免费| 欧美在线欧美在线| 欧美大奶子在线| 韩国三级电影久久久久久| 久久久91精品国产一区不卡| 亚洲电影在线看| 亚洲国产女人aaa毛片在线| 国产精品久久精品| 精品亚洲一区二区三区四区五区| 亚洲精品免费一区二区三区| 日韩视频在线免费观看| 国产欧美一区二区三区视频| 亚洲国产中文字幕在线观看| 亚洲午夜精品久久久久久性色| 成人一区二区电影| 久久久精品一区二区| 欧美性高潮床叫视频| 少妇久久久久久| 国产在线精品一区免费香蕉| 亚洲国产精品99| 欧美日本啪啪无遮挡网站| 一夜七次郎国产精品亚洲| 久久精品人人爽| 中文字幕无线精品亚洲乱码一区| 欧美亚洲第一区| 亚洲欧美国产日韩天堂区| 国产在线视频2019最新视频| 成人国产精品色哟哟| 久久久久中文字幕2018| 亚洲在线观看视频| 91地址最新发布| 成人国内精品久久久久一区| 久久久av亚洲男天堂| 亚洲精品综合久久中文字幕| 日韩精品在线视频| 97在线观看免费| 欧美性做爰毛片| 中文字幕亚洲一区| 深夜成人在线观看| 国产精品久久久久久久av电影| 国产精品偷伦一区二区| 欧美在线激情网| 97免费中文视频在线观看| 成人黄色免费片| 国产精品第一区| 国产成人精品视频在线| 日韩欧美在线视频免费观看| 国产伊人精品在线| 色综合91久久精品中文字幕| 欧美中文在线观看| 国产精品久久久久久久app| 欧美性xxxx极品高清hd直播| 高跟丝袜欧美一区| 国产91热爆ts人妖在线| 久久久久久久色| 亚洲无线码在线一区观看| 久久中文字幕在线| 亚洲男人7777| 亚洲福利影片在线| 久久久久久久久久久久久久久久久久av| 大桥未久av一区二区三区| 91性高湖久久久久久久久_久久99| 欧美日本在线视频中文字字幕| 欧美视频在线观看免费| 亚洲欧美www| 亚洲男人天堂手机在线| 日韩欧美一区二区三区久久| 色综合久久悠悠| 亚洲欧洲xxxx| 欧美中文字幕在线视频| 精品欧美aⅴ在线网站| 久久精品国产96久久久香蕉| 国产精品夫妻激情| 欧美日韩国产丝袜美女| 成人黄色中文字幕| 亚洲人免费视频| 77777少妇光屁股久久一区| 亚洲mm色国产网站| 久久久久久亚洲精品不卡| 91日韩在线播放| 日韩欧美一区视频| 欧美一区二区大胆人体摄影专业网站| 久久色精品视频| 日韩美女在线播放| 中文字幕在线观看亚洲| 精品激情国产视频| 在线观看日韩视频| 国产91在线高潮白浆在线观看| 欧美在线亚洲一区| 亚洲精品99久久久久中文字幕| 亚洲成人久久久| 国产欧美一区二区三区久久| 成人综合网网址| 97国产在线视频| 亚洲精品免费网站| 成人久久18免费网站图片| 欧美日本在线视频中文字字幕| 中文字幕日韩精品有码视频| 国产精品露脸自拍| 国产精品亚洲片夜色在线| 亚洲精品自产拍| 国产91精品久| 国产97色在线| 亚洲国产精品成人va在线观看| 国产精品午夜视频| 人九九综合九九宗合| 91av免费观看91av精品在线| 日本成人激情视频| 91国产精品91| 国产激情久久久| 精品国产鲁一鲁一区二区张丽| 日本午夜精品理论片a级appf发布| 97在线免费观看视频| 日本午夜精品理论片a级appf发布| 国产日本欧美一区二区三区在线| 欧美黑人xxxx| 色yeye香蕉凹凸一区二区av| 欧美野外wwwxxx| 精品免费在线观看| 97国产在线观看| 欧亚精品在线观看| 欧美精品精品精品精品免费| 国产亚洲一区精品| 欧美激情中文字幕乱码免费| 九九热这里只有精品6| 国产人妖伪娘一区91| 国产精品视频最多的网站| 亚洲欧美日韩第一区| 久久香蕉国产线看观看av| 国产自产女人91一区在线观看|