日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

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

编程问答

认识JVM--第一篇-对象分配回收算法

發(fā)布時(shí)間:2024/9/30 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 认识JVM--第一篇-对象分配回收算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://blog.csdn.net/xieyuooo/article/details/6553588


本來標(biāo)題黨想寫成《深入JVM》,不過不太敢寫,我想一小篇博客我想還不足以說明JVM,在本文中,會(huì)就我所知給大家介紹JVM的很多內(nèi)部知識(shí),概念會(huì)相對(duì)較粗,因?yàn)樘?xì)的內(nèi)容要寫,這里肯定寫不出來;本文主要偏重理論,沒有什么實(shí)踐,中間除一些官方資料外,還有部分自身的理解,所以請(qǐng)大家不要完全信任本文內(nèi)容;另外本文會(huì)有一小部分糾正以前一篇文章對(duì)于intern()使用方法的錯(cuò)誤,本文會(huì)在其中說明使用錯(cuò)誤的原因,大致文章內(nèi)容有以下幾個(gè)部分:

?

1、JVM虛擬內(nèi)存組成及操作系統(tǒng)地址表

2、新生成對(duì)象在HeapSize是如何變化的

3、虛擬機(jī)如何定義回收算法

4、JVM占用的空間除HeapSize還會(huì)占用什么,OutOfMemory種類!

5、糾正錯(cuò)誤:intern()的使用上的錯(cuò)誤

?

?

好,現(xiàn)在開始話題吧:

1、JVM虛擬內(nèi)存組成及操作系統(tǒng)地址表

?

?????1.1.虛擬地址大致概念:在OS層面一般是由邏輯地址映射到線性地址,如果線性地址管理,如果啟動(dòng)了分頁,那么線性地址就會(huì)轉(zhuǎn)換到相應(yīng)的物理地址上,否則就直接認(rèn)為是物理地址;程序設(shè)計(jì)中所用到的地址單元就是邏輯單元,如在C語言中的&表示指定的地址就是邏輯地址;而物理地址也并非我們所認(rèn)為的RAM,還應(yīng)該包括網(wǎng)卡、顯存、SWAP等相關(guān)內(nèi)容,也就是由OS所管理所有可以通過頂層邏輯單元映射到的目標(biāo)地點(diǎn),不過絕大部分情況下只需要考慮RAM即可,尤其是在服務(wù)器上;JVM的虛擬內(nèi)存地址和操作系統(tǒng)的虛擬內(nèi)存地址不是一個(gè)概念,操作系統(tǒng)的虛擬內(nèi)存地址相當(dāng)于在磁盤上劃分的一個(gè)SWAP交換區(qū),用于內(nèi)存,內(nèi)存與之做page out和page in的操作,這種用于物理內(nèi)存本身不夠,而地址空間夠用的情況,一旦程序出現(xiàn)page out這些情況的時(shí)候,程序?qū)?huì)變得非常緩慢,而JVM的虛擬內(nèi)存是在有效的空間內(nèi)分配一個(gè)連續(xù)的線性地址空間,因?yàn)镴VM想要自己管理內(nèi)存,分配的堆內(nèi)存都是在自己的heapSize內(nèi)部,因?yàn)樗獙?shí)現(xiàn)一些脫離于存儲(chǔ)器本身對(duì)非連續(xù)堆處理的管理而導(dǎo)致的復(fù)雜性,也就是JVM去初始化的時(shí)候就會(huì)加載一塊很大的內(nèi)存單元,然后內(nèi)部的操作都是內(nèi)部自己完成的。


????1.2.內(nèi)存分配:一般C語言分配內(nèi)存是初始化將相應(yīng)的基本內(nèi)容和代碼段進(jìn)行加載,但是不會(huì)加載運(yùn)行時(shí)候的堆棧內(nèi)存分配,也就是在運(yùn)行到某個(gè)具體的函數(shù)時(shí)通過malloc、callloc、realloc等方方申請(qǐng)的區(qū)域,這些區(qū)域必須從操作系統(tǒng)中重新來分配,使用完成后必須進(jìn)行free,C++中必須使用delete方法來釋放,大家發(fā)現(xiàn)沒有,OS的堆在內(nèi)存不斷申請(qǐng)和釋放的過程中,必然會(huì)產(chǎn)生許多的內(nèi)存碎片,從而導(dǎo)致你在申請(qǐng)一塊大內(nèi)存的時(shí)候,需要進(jìn)行邏輯連接,導(dǎo)致在申請(qǐng)的速度減小,當(dāng)然LINUX采用了將內(nèi)存塊劃分為多個(gè)不同大小的板塊,來較好的處理這個(gè)問題,不過片段還是存在的,不過這種思想的確是很好的,而JVM是如何完成碎片的處理的呢,后面章節(jié)會(huì)說到;JVM在初始化的時(shí)候就會(huì)向OS申請(qǐng)一塊大內(nèi)存,JVM要求這塊內(nèi)存在地址空間上是連續(xù)的(物理上未必連續(xù)),讓所有的程序在這個(gè)內(nèi)部區(qū)分配,由自己來管理,所以它內(nèi)部相當(dāng)于做了一個(gè)小的OS對(duì)內(nèi)存的管理,所以JVM是想讓java程序員不用關(guān)心在哪一個(gè)平臺(tái)上寫代碼,但是你一定要關(guān)心java怎么管理內(nèi)存的;

??? 線性地址隨著實(shí)際物理內(nèi)存的增加,將會(huì)導(dǎo)致頁表非常大,甚至于導(dǎo)致多層頁表,如內(nèi)存達(dá)到96G這一類,那么這樣管理起來將會(huì)非常麻煩(正常情況下一個(gè)頁只有4K,可以自己算一下需要多少個(gè)管理地址來指向這個(gè)4K,這個(gè)管理地址太大的時(shí)候,又需要其他的管理地址來管理這個(gè)地址,就會(huì)導(dǎo)致多層地址,可能到最后,一個(gè)大內(nèi)存有40%都是用于管理內(nèi)存的,真正使用的可想而知),所以在LINUX高版本中對(duì)于內(nèi)存尋址方面做了改進(jìn),就是支持大頁面來支持(其實(shí)是通過一個(gè)套件完成的,并非OS本身),如一個(gè)頁的大小為1M這樣的,但是有一些風(fēng)險(xiǎn)在里面,它要求大頁面內(nèi)存要么放得下你的內(nèi)存,但是你不能將你的進(jìn)程一部分放在大頁面內(nèi)存中,一部分放在OS管理的小頁面內(nèi)存中,也就是說要么這塊放得下,要么就放在其他地方,可能會(huì)導(dǎo)致兩邊正好都差那么一點(diǎn)點(diǎn)的問題,在OS這邊可以使用SWAP,但是系統(tǒng)會(huì)很慢,而且SWAP很多的情況下肯定會(huì)宕機(jī)掉。


????1.3.內(nèi)存分配狀態(tài):一個(gè)大的進(jìn)程如果初始化需要分配一塊大的內(nèi)存空間,內(nèi)存空間一般會(huì)經(jīng)歷兩個(gè)狀態(tài)的轉(zhuǎn)換過程,首先內(nèi)存必須是free狀態(tài)才可以被分配,如果的確是該狀態(tài)并且空間是夠用的,那么它首先會(huì)占用那么大一個(gè)坑,在java的heapSize中,就是-Xmx參數(shù)指定的,也就是JVM虛擬機(jī)最大的內(nèi)存空間(注意這里-Xmx并沒有包含PermSize的空間),這個(gè)坑是不允許其它進(jìn)程所占用的,內(nèi)存的狀態(tài)為:reserved的狀態(tài),當(dāng)需要使用的空間時(shí),內(nèi)存將會(huì)被commited狀態(tài),在JVM初始化時(shí)也就是-Xms狀態(tài)的內(nèi)存空間,處于這個(gè)狀態(tài)的內(nèi)存如果發(fā)現(xiàn)不夠使用(物理內(nèi)存),此時(shí)就會(huì)發(fā)生swap區(qū)域,程序?qū)?huì)變得非常緩慢,但是不會(huì)造成宕機(jī),而很多時(shí)候在這個(gè)時(shí)候定位不出原因,所以我們?yōu)榱俗屛锢韮?nèi)存不夠用的現(xiàn)象暴露出來可以被發(fā)現(xiàn),至于可以定位不是程序代碼的問題,我們就直接將swap內(nèi)存禁用掉;有個(gè)問題就是既然被reserved的內(nèi)存就不能被其他進(jìn)程所占用,為什么要在這兩個(gè)狀態(tài)之間來回倒騰呢?這不是多一個(gè)開銷嗎?JVM在來回倒騰的過程中會(huì)導(dǎo)致每個(gè)區(qū)域的容量發(fā)生相應(yīng)的變化,必然導(dǎo)致的是FullGC的過程,那么JVM一般在服務(wù)器端如何設(shè)置呢?文章后面逐步細(xì)化說明。


????1.4.JVM內(nèi)存組織:關(guān)于JVM內(nèi)存組織方面,前面在講述Java垃圾回收的時(shí)候已經(jīng)提及到了,但是講得不太細(xì),有些部分可能算是有錯(cuò)誤的,所以這里根據(jù)上述操作系統(tǒng)知識(shí)以及官方部分資料繼續(xù)深入,不敢說完全正確,不過至少比以前要更加深入得多,首先來看下ORACLE官方給出來的一個(gè)JVM內(nèi)存單元的組織圖形:

?

?

其實(shí)我看過很多次這個(gè)圖看得很暈,因?yàn)橐郧安涣藘?nèi)存分配中commited與reserved的區(qū)別,以至于我當(dāng)時(shí)認(rèn)為這副圖是說java的HeapSize是由N多個(gè)部分組成的,并且還包含HeapSize的,其實(shí)在經(jīng)過很多資料查閱后,尤其是看到一些監(jiān)控工具后,才知道看官方資料也有誤區(qū),呵呵,通過簡(jiǎn)化,我自己畫的這副圖希望能夠幫助大家理解JVM的大致的內(nèi)存劃分(這里僅僅提及JVM自己的內(nèi)存,也就是HeapSize和PermSize的部分,其余的文章后面說明),這里僅僅將上面的圖形立起來畫了,當(dāng)時(shí)看起來要方便理解得很多(個(gè)人感覺):

?

?

也就是說,你首先需要將JVM的兩個(gè)大板塊分開,一個(gè)是HeapSize,也就是上圖左側(cè)的部分,右邊部分為PermSize的尺寸,HeapSize也劃分為大區(qū)域?yàn)閅oung和Old區(qū)域,Young區(qū)域內(nèi)部劃分為三個(gè)部分,一個(gè)是Eden和兩個(gè)同樣尺寸大小的survivor區(qū)域,注意到的人會(huì)發(fā)現(xiàn)為什么每個(gè)區(qū)域內(nèi)部還有一個(gè)virtual區(qū)域,這就是我們上面說的沒有經(jīng)過commited當(dāng)時(shí)已經(jīng)占用了地址列表,它不能被其他進(jìn)程所占用,當(dāng)時(shí)操作系統(tǒng)一般的提示會(huì)認(rèn)為這是塊剩余空間,但是實(shí)際上是只能被自己使用的,這部分上面已經(jīng)提及,至于為什么我們后面來解釋,這里再提出一些問題,就是為什么JVM要提出這么多區(qū)域劃分來管理呢?如果一個(gè)區(qū)域可以管理為什么還要搞得那么麻煩呢?這么多區(qū)域有什么用處,我們?cè)诘诙聦?duì)象的分配中將詳細(xì)說明這部分內(nèi)容。

?

?

2、新生成對(duì)象在HeapSize是如何變化的

??? 2.1.java新創(chuàng)建對(duì)象的方法有哪些:首先學(xué)習(xí)過java的人可能沒有人不知道new 這個(gè)關(guān)鍵字,也就是新創(chuàng)建一個(gè)對(duì)象的關(guān)鍵字,當(dāng)發(fā)生new操作時(shí),jvm為你做了什么?我們先把這個(gè)問題放下,對(duì)于jvm初始化加載專門處理,這里先說除了new之外還有什么方式,就是通過java.lang.Class.forName進(jìn)行動(dòng)態(tài)狀態(tài)后,獲取一個(gè)新的實(shí)例,當(dāng)然方法有重載,也通過通過ClassLoader進(jìn)行動(dòng)態(tài)狀態(tài),什么是動(dòng)態(tài)裝載?為什么有了new還要有動(dòng)態(tài)裝載?而jvm初始化做了什么?動(dòng)態(tài)裝載和new的區(qū)別是什么?這也是我們下面要討論的問題,也是PermSize中內(nèi)容的一大塊部分。

?

???2.2.jvm初始化需要做什么?Jvm在向OS請(qǐng)求了一塊地址列表后,然后就需要初始化了,初始化要做什么呢?jvm啟動(dòng)相當(dāng)于一個(gè)進(jìn)程,當(dāng)然它可以再啟動(dòng)子進(jìn)程,這里我我們只考慮單個(gè)進(jìn)程,進(jìn)程啟動(dòng)必然需要初始化一些內(nèi)容,C語言或者C++它會(huì)將相應(yīng)的全局變量以及代碼段等內(nèi)容在內(nèi)存中進(jìn)行編譯為相應(yīng)的指令集;而jvm做了什么呢?jvm它也需要做一些操作;首先每一個(gè)進(jìn)程都必須最少一個(gè)引導(dǎo)進(jìn)程,也就是我們說的main,通過引導(dǎo)進(jìn)程所關(guān)聯(lián),以及關(guān)聯(lián)的關(guān)聯(lián)(也就是import),jvm會(huì)將這些關(guān)聯(lián)關(guān)系的內(nèi)容形成一個(gè)大的jvm網(wǎng)狀結(jié)構(gòu)用于關(guān)系于class之間并保證每一個(gè)class有一份自己的私有池,他們放在哪里,他們就是放在PermSize,也就是很多中文翻譯中的永久代,每一個(gè)Class都有自己獨(dú)立的私有池去管理自身的結(jié)構(gòu),對(duì)一個(gè)java程序源文件,編寫的是對(duì)于程序的描述信息,生成class也就是描述信息的byte格式(在這個(gè)過程中會(huì)自動(dòng)完成一些簡(jiǎn)單邏輯合并工作),byte格式是字節(jié)碼格式,也就是按照每8個(gè)bit位組成的計(jì)算機(jī)基本格式,只要字符集統(tǒng)一,則為每一個(gè)操作系統(tǒng)所認(rèn)知的格式,JVM需要做的是將這些統(tǒng)一認(rèn)知的格式信息翻譯為對(duì)應(yīng)操作系統(tǒng)的指令或硬件指令,所以JVM真正的意義就是為每一個(gè)操作系統(tǒng)編寫了一個(gè)統(tǒng)一的JRE,即:java運(yùn)行時(shí)環(huán)境,而編譯環(huán)境是所有系統(tǒng)都可以使用的;初始化將class的定義加載到內(nèi)存中會(huì)進(jìn)行相應(yīng)的轉(zhuǎn)換和壓縮,總之會(huì)形成原有對(duì)類型描述和執(zhí)行順序,而不會(huì)出現(xiàn)混亂,但并不是對(duì)應(yīng)的操作系統(tǒng)指令(對(duì)應(yīng)的操作系統(tǒng)指令是運(yùn)行時(shí)知道的),如描述類型、作用域、訪問權(quán)限等等內(nèi)容,這部分空間大小決定于class的多少,也就是你的工程的大小,PermSize還包含了其他的內(nèi)容,并且只是在一般情況下不會(huì)發(fā)生GC,但是有些時(shí)候還是會(huì)發(fā)生GC的,在后面繼續(xù)說明;這個(gè)加載完成后,他們?cè)诔刂凶匀挥凶约旱膬?nèi)存首地址,要尋找他必然要有對(duì)應(yīng)列表,列表的基礎(chǔ)肯定是屬于符號(hào)向量了,也就是基于名稱的一個(gè)符號(hào)向量,那么當(dāng)發(fā)生new時(shí),它會(huì)在符號(hào)向量中尋找對(duì)應(yīng)的class,找到后將符號(hào)地址轉(zhuǎn)換為對(duì)應(yīng)的class地址,并且這個(gè)內(nèi)容只會(huì)被轉(zhuǎn)載一次,以后可以直接被利用,從中找到了class的定義,在堆中分配內(nèi)存時(shí)將其定義部分的某些組織單元放置與對(duì)象的頭部,這些代碼段對(duì)于對(duì)象來說是彼此獨(dú)立,就像你在方法體前面增加synchronize關(guān)鍵字,對(duì)于非靜態(tài)方法來說,不同的對(duì)象這個(gè)關(guān)鍵字是相互不會(huì)影響的,也就是說,如果多個(gè)線程調(diào)用的對(duì)象不是同一個(gè),僅僅在方法(非靜態(tài)方法)體上面增加synchronized這對(duì)于多線程同步是無效的(更多關(guān)于多線程的知識(shí),如關(guān)鎖方面的Lock、Atomic等方面的知識(shí)不是本文的內(nèi)容,這里不再展開討論);注意,這里還沒有談到申請(qǐng)對(duì)象以及動(dòng)態(tài)裝載,動(dòng)態(tài)裝載的class一般是不會(huì)JVM初始化的時(shí)候轉(zhuǎn)入Perm的,而是運(yùn)行時(shí)動(dòng)態(tài)裝載進(jìn)去的,就像JDBC驅(qū)動(dòng)一樣,大家?guī)缀醵加脛?dòng)態(tài)裝載來實(shí)現(xiàn)動(dòng)態(tài)加載不同數(shù)據(jù)庫連接的目的;也就是我們上一節(jié)提出的問題,動(dòng)態(tài)裝載做什么?它負(fù)責(zé)的是運(yùn)行時(shí)裝載一些類的定義,而不是初始化,當(dāng)然,當(dāng)你通過全名去加載的時(shí)候,他們會(huì)從符號(hào)向量中尋找這個(gè)類是否已經(jīng)加載,如果已經(jīng)加載則直接使用,否則從相應(yīng)的包中獲取這個(gè)class定義,然后裝載起來,裝載的單位也是以class為單位,并不是以jar包為單位,這里請(qǐng)大家如果不要濫用動(dòng)態(tài)加載,一個(gè)是造成Perm的不穩(wěn)定,另一個(gè)是它的效率肯定沒有new高,因?yàn)樗枰热ネㄟ^符號(hào)向量尋找是否存在,不存在再加載,然后再通過newInstance實(shí)例化一個(gè)或多個(gè)實(shí)例,當(dāng)然在某些特殊的時(shí)候,利用它可以為你的程序帶來極高的靈活性。

?

??2.2.內(nèi)存申請(qǐng)時(shí)的指針與實(shí)例:內(nèi)存申請(qǐng)時(shí)上一節(jié)已經(jīng)說到地址空間的和符號(hào)引用得到對(duì)應(yīng)數(shù)據(jù)結(jié)構(gòu)的方法,這里不再提及,這里就將對(duì)象作為整體,在堆中;在JVM的初衷中,它希望新申請(qǐng)的內(nèi)存是連續(xù)的,雖然堆的定義是讓內(nèi)存是隨機(jī)分配的,但是對(duì)于整個(gè)JVM來說,它希望分配的內(nèi)存是較為連續(xù)的,也就是按照較為條帶化的方式進(jìn)行分配,好處有好幾個(gè),一個(gè)是這樣非常的簡(jiǎn)單,經(jīng)過精簡(jiǎn)后的情況目前一個(gè)new翻譯為機(jī)器碼只需要10條左右的指令碼,近乎與C語言,所以在高版本的jdk中,new的開銷不再是java虛擬機(jī)慢的一個(gè)原因,大家也沒有必要去盡量減少new,但是也不要濫用,業(yè)績(jī)雖亂定義不必要的對(duì)象;其次,另一個(gè)好處,當(dāng)內(nèi)存較為連續(xù)后,內(nèi)存在分配上就沒有類似的大量碎片的問題,造成運(yùn)行一段時(shí)間后,大量碎片,當(dāng)需要申請(qǐng)一個(gè)大內(nèi)存的時(shí)候,需要尋找非常多的地方才能將其邏輯上組成,而導(dǎo)致分配空間上不必要的浪費(fèi);而一個(gè)簡(jiǎn)單內(nèi)存分配String?a =?new?String("abc");,這樣一條代碼,會(huì)做什么動(dòng)作呢?a相當(dāng)于是對(duì)象的一個(gè)指針一樣的東西,這個(gè)空間的大小為一個(gè)long的長(zhǎng)度,也就是可以支持到可以想象的任何內(nèi)存大小,它并不是存放在heapSize中的,而是放在stack中的,由OS來調(diào)度管理,也就是當(dāng)a的作用區(qū)域完成,這個(gè)指針將會(huì)斷開,java中的String不再是C或者C++中的一個(gè)指針指向的一個(gè)字符數(shù)組,而是一個(gè)被包裝后的對(duì)象,也就是java為什么說自己都是對(duì)象,因?yàn)樗言鷳B(tài)的內(nèi)容進(jìn)行了包裝,讓程序編寫更加簡(jiǎn)單;這里順便提及一下:在較早期的jdk中,jvm并不是由一個(gè)指針直接指向分配堆中的首地址,而是先有一個(gè)handle空間,這個(gè)空間存放了開始說的一些對(duì)象的定義和結(jié)構(gòu)信息,也就是找到該位置,然后由該位置轉(zhuǎn)換到對(duì)應(yīng)的對(duì)象上,但是那個(gè)時(shí)候的對(duì)象頭部信息就沒有現(xiàn)在的那么全,也就是以前是將一部分handle內(nèi)容放置在獨(dú)立的空間上,現(xiàn)在的jdk已經(jīng)沒有那樣的了。

?

???2.3.內(nèi)存分配后放在哪里,如何移動(dòng)

終于回到上面的話題,內(nèi)存分配后,在堆中的什么位置?就是我們上面說的heapSize中的Young區(qū)域的Eden區(qū)域中,也就是new的對(duì)象絕大部分會(huì)放在這里(排除一種非常大的對(duì)象的特殊情況),在java設(shè)計(jì)的看來有一個(gè)特別有意思的地方,就是它在新生成的對(duì)象中它認(rèn)為你絕大部分對(duì)象都是應(yīng)該需要被銷毀掉的,就像在做java WEB應(yīng)用上一樣,一個(gè)列表請(qǐng)求過來,可能請(qǐng)求的內(nèi)容有2K的內(nèi)容,請(qǐng)求完成后,這個(gè)內(nèi)容一般說來自然就不需要了,也就是在他原始的考慮下它沒有考慮你自己在應(yīng)用級(jí)別去做page cache的操作;好,那么當(dāng)內(nèi)存不夠的時(shí)候,這里指被commited的空間不夠的情況下,此時(shí)java就會(huì)做一個(gè)動(dòng)作,就是會(huì)對(duì)Young空間進(jìn)行回收,由于新生成的對(duì)象,java認(rèn)為這塊空間不會(huì)很大,而且絕大部分應(yīng)該是被干掉的內(nèi)容,所以很多時(shí)候java會(huì)采用單線程的復(fù)制算法(當(dāng)然你也可以設(shè)置為多線程),關(guān)于算法的核心在第三章中會(huì)說到,這里總之先理解找到了活著的對(duì)象,將其拷貝到其中一個(gè)survivor區(qū)域中,當(dāng)下一次做操作時(shí),就會(huì)將Eden中活著的以及前一個(gè)surivor活著的一起拷貝到另一個(gè)survivor中,這就是為什么要設(shè)置兩個(gè)survivor區(qū)域,而拷貝后,Eden區(qū)域?yàn)榭铡⒘硪粋€(gè)survivor也為空,可以完全直接整體清除掉,所以非常快速,而拷貝的目標(biāo)也會(huì)被連續(xù)化,新生成的對(duì)象又從Eden的初始位置開始分配空間。

????? 當(dāng)對(duì)象每次(活著)被拷貝到一個(gè)survivor時(shí),Java虛擬機(jī)就會(huì)記錄下來對(duì)象被移動(dòng)的次數(shù),當(dāng)次數(shù)達(dá)到一定的程度,也就是官方文檔所說的足夠老的情況,這塊內(nèi)存就認(rèn)為它不太容易被注銷掉,此時(shí)就會(huì)被移動(dòng)到第二個(gè)區(qū)域Tenured區(qū)域,這個(gè)次數(shù)也可以由自己來控制。

????? 另外在一般默認(rèn)的情況下當(dāng)回收后的內(nèi)存仍然占用實(shí)際目前commited內(nèi)存的70%以上,那么此時(shí)虛擬機(jī)將會(huì)開始擴(kuò)展這些內(nèi)存,而當(dāng)回收后的內(nèi)存小于40%后,虛擬機(jī)將會(huì)降低這部分內(nèi)存,但是其他線程仍然不能使用(當(dāng)然這個(gè)參數(shù)也是可配置的,在文章最后有說明),這樣收縮和擴(kuò)展必然導(dǎo)致一些問題,但是java的初衷是想讓你再?zèng)]有使用這塊地址表的時(shí)候,回收內(nèi)存的大小會(huì)小一些,因?yàn)閥oung區(qū)域的一般是使用單線程的回收方式,這個(gè)時(shí)間段是會(huì)被暫停的,所以它認(rèn)為內(nèi)存使用較少的時(shí)候回收就內(nèi)存的速度應(yīng)該加快;但是,和實(shí)際相反的是,我們正好需要的是內(nèi)存使用較大的時(shí)候,才希望加快回收的速度,內(nèi)存使用小的時(shí)候,回收都是無所謂的;所以我們?cè)诤芏鄷r(shí)候建議將-Xms和-Xmx設(shè)置成一樣的大小,不用這么來回倒騰。

???? 在說明下,以下三種情況對(duì)象會(huì)被晉升到old區(qū)域:

???? 1、在eden和survivor中可以來回被minor gc多次,這個(gè)次數(shù)超過了-XX:MaxTenuringThreshold

?????2、在發(fā)生minor gc時(shí),發(fā)現(xiàn)to survivor無法放下這些對(duì)象,就會(huì)進(jìn)入old。

???? 3、在新申請(qǐng)對(duì)象,大于eden區(qū)域的一半大小時(shí)直接進(jìn)入old,也可以專門設(shè)置參數(shù)-XX:PretenureSizeThreshold這個(gè)參數(shù)指定當(dāng)超過這個(gè)值就直接進(jìn)入old。

?

?

???? 當(dāng)上面的對(duì)象被移動(dòng)到了Tenured區(qū)域,這個(gè)區(qū)域一般非常大,占用了HeapSize的絕大部分空間,此時(shí)若它發(fā)生一次內(nèi)存回收,就不能像剛才那樣來回拷貝了,那樣代價(jià)太大,而且這個(gè)區(qū)域可以說是經(jīng)得起考驗(yàn)的對(duì)象才會(huì)被移動(dòng)過來,在概率上是不容易被銷毀掉的對(duì)象才會(huì)被移動(dòng)過來;那么,我們很此時(shí)想到的就是反過來計(jì)算,也就是找到需要銷毀的對(duì)象,將其銷毀,關(guān)于算法也是下面第三章要說的內(nèi)容,總之對(duì)象會(huì)在這里存放著。

?

???? 為什么java不論在Young中的區(qū)域會(huì)來回倒騰,而在Tenured區(qū)域也會(huì)不斷去做壓縮,就是我們前面說的,它希望內(nèi)存相對(duì)較為連續(xù)而做的;java在Yong的區(qū)域,它認(rèn)為可以剩下的內(nèi)容不會(huì)很多,所以拷貝的代價(jià)并不大,所以它認(rèn)為來回拷貝是一種合適的方法,而Tenured區(qū)域它采用了清除后,一定次數(shù)后進(jìn)行壓縮的方式,當(dāng)然這個(gè)次數(shù)你可以自己去設(shè)置,在文章的最后是有參數(shù)的;而它沒有采用類似操作系統(tǒng)一樣的按照板塊大小等一系列算法來完成,這也是我比較納悶的事情,不過總體說來這種算法還是可行的;希望在劃分區(qū)域一些策略上能有更大的靈活性,這樣可以在更多的應(yīng)用中發(fā)揮得更加靈活,這樣就更好了;比較困惑的就是這樣的架構(gòu)自己如果做頻繁度不高不低的page cache,性能不好估量,也許比不做cache更低,這個(gè)要根據(jù)具體情況而定了。


????2.3.Perm一般還會(huì)存放什么內(nèi)容?Perm除了存放上面的Class定義外,還一般會(huì)存放的內(nèi)容有靜態(tài)代碼段、final static類型的類變量、String常量以及String被intern后的內(nèi)容,也是最后一章中所要提及以前我自己寫錯(cuò)的內(nèi)容;如何應(yīng)對(duì)好常量池,以及常量池是否會(huì)被GC,也是我們所需要說明的內(nèi)容;關(guān)于Perm永久代中存放的內(nèi)容,應(yīng)當(dāng)如何配置以至于它可以去回收,在文章的最后有相應(yīng)的說明,請(qǐng)自行查閱;不過對(duì)于Perm的大小,一般還是不建議去做GC的,也就是合理的去使用Perm,在程序運(yùn)行中占用Perm最多的就是String常量,尤其是如果大量使用intern的時(shí)候,就會(huì)造成大量Perm膨脹,也是最后一部分需要說明的內(nèi)容,不過intern也并非一無是處,因?yàn)槟憧梢赃@樣說:如果它沒有用處的話,java沒有必要再把String的常量放在單獨(dú)的一個(gè)地方,它有很多好處,只要在適當(dāng)?shù)臅r(shí)候利用好常量池這個(gè)區(qū)域在必要的時(shí)候可以提高性能,具體在最后一章有所講解。

?

?

?

3、虛擬機(jī)如何定義回收算法

??? 3.1.首先虛擬的回收算法會(huì)分成兩個(gè)部分,一個(gè)部分是對(duì)象的查找算法,一個(gè)是真正如何回收的方法。一般對(duì)于查找有以下兩種:

??? a)引用計(jì)數(shù):本來在本文中我不想提及引用計(jì)數(shù),因?yàn)檫@是最原始也是最垃圾的算法,也是較低版本jdk慢得出奇的原因,但是為了說明后面的問題不得不簡(jiǎn)單說明一下,引用計(jì)數(shù)就是通過java虛擬機(jī)專門為每個(gè)對(duì)象記錄它被指針指向的個(gè)數(shù),當(dāng)發(fā)生指針指向它或者被賦值,計(jì)數(shù)器將會(huì)被加1,而但指向它的指針=null或者脫離了作用區(qū)域,jvm就會(huì)將相應(yīng)的計(jì)數(shù)器減少1,這樣簡(jiǎn)單,但是慢死了,不僅僅操作上出奇的慢,因?yàn)橐鲆粋€(gè)簡(jiǎn)單的賦值操作要到多個(gè)地方去找一大堆東西;還有一個(gè)就會(huì)引起很難檢測(cè)到的內(nèi)存泄露,那就是當(dāng)兩個(gè)或者多個(gè)對(duì)象存在循環(huán)交叉引用的時(shí)候,此時(shí)他們的引用計(jì)數(shù)將永遠(yuǎn)不會(huì)等于0(如使用雙向鏈表或使用復(fù)雜的集合類后,相互之間的引用),也就是垃圾收集器將永遠(yuǎn)不會(huì)認(rèn)為這是垃圾(當(dāng)然要用復(fù)雜的算法可以解決,但是這個(gè)算法的確很復(fù)雜,可能垃圾回收會(huì)更加慢),最后就是這個(gè)垃圾回收方式必然導(dǎo)致內(nèi)存的遍歷操作過程。引用計(jì)數(shù)的示意圖如下圖所示:

?

?

?

????b)引用樹遍歷:其實(shí)是一個(gè)圖,只是有根而已,它沿著對(duì)象的根句柄向下查找到活著的節(jié)點(diǎn),并標(biāo)記下來,其余沒有被標(biāo)記的節(jié)點(diǎn)就是死掉的節(jié)點(diǎn),這些對(duì)象就是可以被回收的,或者說活著的節(jié)點(diǎn)就是可以被拷貝走的,具體要看所在heapSize中的區(qū)域以及算法,它的大致示意圖如下圖所示(對(duì)象:B、G、D、J、K、L、F都是垃圾對(duì)象,雖然他們也有相互指向,但是不是被根節(jié)點(diǎn)能遍歷到的,注意這里是指針是單向的):

?

?

?

????3.2.內(nèi)存回收:上面的方法我們可以找到內(nèi)存可以被使用的,或者說那些內(nèi)存是可以回收,更多的時(shí)候我們肯定愿意做更少的事情達(dá)到同樣的目的,我們會(huì)根據(jù)一般的情況設(shè)置不同的算法來讓系統(tǒng)的性能達(dá)到較好的程度,首先來了解下內(nèi)存回收的算法或者它的經(jīng)歷有哪些?

????a):標(biāo)記清除算法,這算是比較原始的算法,也就是通過上面的查找標(biāo)記后,我們對(duì)沒有標(biāo)記的對(duì)象進(jìn)行空間釋放的過程,這個(gè)算法雖然很原始,但是是后來所有算法的基礎(chǔ),好處的簡(jiǎn)單,缺陷是造成和其他語言一樣的內(nèi)存碎片,要通過更加復(fù)雜的算法來解決這些碎片;另一缺陷就是它這個(gè)過程如果用于較大的內(nèi)存將會(huì)導(dǎo)致長(zhǎng)時(shí)間的對(duì)外服務(wù)停止(當(dāng)然這個(gè)停止也不是傳說中那么長(zhǎng),只是相對(duì)計(jì)算機(jī)來說比較長(zhǎng),至于多長(zhǎng)是還和jdk的版本以及廠商有關(guān)系,BEA曾經(jīng)在1G的JVM下面測(cè)試,有300M空間屬于可用空間,據(jù)測(cè)試結(jié)果為30ms的停止服務(wù)時(shí)間,我想這個(gè)時(shí)間應(yīng)該可以接受,不過它有自己的測(cè)試場(chǎng)景,不能完全說明問題,而一般情況下在單線程引用下,常規(guī)的回收起碼會(huì)比這個(gè)時(shí)間要長(zhǎng)好幾倍甚至于10倍以上)。

????b):標(biāo)記清楚壓縮,這個(gè)算法是也是較為原始的,它的出現(xiàn)是為了解決上面一種算法中不能壓縮空間的問題,但是并非取代,因?yàn)樗鼘?dǎo)致的另一個(gè)問題就是更長(zhǎng)時(shí)間的服務(wù)停止,因?yàn)閴嚎s就是空間拷貝到一個(gè)較為連續(xù)的地方,而并非對(duì)數(shù)據(jù)本身進(jìn)行壓縮,所以很多時(shí)候他們是配合使用的,如多少次清除后進(jìn)行一次壓縮。

???c)復(fù)制回收:也就是在jvm發(fā)展的過程中出現(xiàn)的算法,現(xiàn)在基本都只能看到一些思想影子在里面,但是沒有這個(gè)方式,也就是將其劃分為2個(gè)相同的大小,然后將活著的節(jié)點(diǎn)來回拷貝,這樣造成的內(nèi)存浪費(fèi)的非常大的,不僅僅是一半的浪費(fèi)問題,而且每次拷貝的開銷也是非常大的,因?yàn)槎际巧婕暗秸麄€(gè)jvm活著節(jié)點(diǎn)的拷貝過程。

???d)增量回收:這算是現(xiàn)代垃圾回收的一個(gè)前身,它做的事情就是為了解決復(fù)制回收算法中的一個(gè)問題,就是每次復(fù)制造成的空間開銷非常大的問題,此時(shí)它將內(nèi)存中切分為逐個(gè)板塊,這些板塊,每個(gè)內(nèi)部使用了復(fù)制算法,也就是并沒有解決空間浪費(fèi)的問題,回收的過程中沒有進(jìn)行細(xì)化,雖然回收速度較快速,而且只會(huì)造成局部的停止服務(wù),但是對(duì)于不同板塊大小、不同生命周期的對(duì)象還是沒有劃分開。

???e)分代收集器:分代收集器是增量收集的另一個(gè)化身,或者說延續(xù)吧,它將板塊按照生命周期劃分為上面所說的板塊,每一個(gè)板塊可以采用不同的算法進(jìn)行回收,這也是和增量回收最大的區(qū)別,此時(shí)可以讓jvm的回收達(dá)到更好的效果,不過由于jvm按照生命周期劃分后都是指定板塊的,所以根據(jù)內(nèi)存大小劃分自定義板塊是不可能的,至少現(xiàn)在好像還沒有,所以在回收過程中如果內(nèi)存大了回收起來一樣很吃力,尤其是對(duì)Old區(qū)域的回收,所以并發(fā)回收不得不出現(xiàn)了。

???f)并發(fā)回收:所謂并發(fā)回收是指外部在訪問的同時(shí),java回收器依然在做著回收工作,原早我認(rèn)為并發(fā)回收是不可能的,因?yàn)槟阈枰纼?nèi)存是需要回收的,就不能讓內(nèi)存繼續(xù)的被申請(qǐng)和釋放,但是SUN的人還是比較天才的,還是有辦法盡量讓他并發(fā)去做的;并發(fā)回收器其實(shí)也會(huì)暫停,但是時(shí)間非常短,它并不會(huì)在從開始回收尋找、標(biāo)記、清楚、壓縮或拷貝等方式過程完全暫停服務(wù),它發(fā)現(xiàn)有幾個(gè)時(shí)間比較長(zhǎng),一個(gè)就是標(biāo)記,因?yàn)檫@個(gè)回收一般面對(duì)的是老年代,這個(gè)區(qū)域一般很大,而一般來說絕大部分對(duì)象應(yīng)該是活著的,所以標(biāo)記時(shí)間很長(zhǎng),還有一個(gè)時(shí)間是壓縮,但是壓縮并不一定非要每一次做完GC都去壓縮的,而拷貝呢一般不會(huì)用在老年代,所以暫時(shí)不考慮;所以他們想出來的辦法就是:第一次短暫停機(jī)是將所有對(duì)象的根指針找到,這個(gè)非常容易找到,而且非常快速,找到后,此時(shí)GC開始從這些根節(jié)點(diǎn)標(biāo)記活著的節(jié)點(diǎn)(這里可以采用并行),然后待標(biāo)記完成后,此時(shí)可能有新的 內(nèi)存申請(qǐng)以及被拋棄(java本身沒有內(nèi)存釋放這一概念),此時(shí)JVM會(huì)記錄下這個(gè)過程中的增量信息,而對(duì)于老年代來說,必須要經(jīng)過多次在survivor倒騰后才會(huì)進(jìn)入老年代,所以它在這段時(shí)間增量一般來說會(huì)非常少,而且它被釋放的概率前面也說并不大(JVM如果不是完全做Cache,自己做pageCache而且發(fā)生概率不大不小的pageout和pagein是不適合的);JVM根據(jù)這些增量信息快速標(biāo)記出內(nèi)部的節(jié)點(diǎn),也是非常快速的,就可以開始回收了,由于需要?dú)⒌舻墓?jié)點(diǎn)并不多,所以這個(gè)過程也非常快,壓縮在一定時(shí)間后會(huì)專門做一次操作,有關(guān)暫停時(shí)間在Hotspot版本,也就是SUN的jdk中都是可以配置的,當(dāng)在指定時(shí)間范圍內(nèi)無法回收時(shí),JVM將會(huì)對(duì)相應(yīng)尺寸進(jìn)行調(diào)整,如果你不想讓它調(diào)整,在設(shè)置各個(gè)區(qū)域的大小時(shí),就使用定量,而不要使用比例來控制;當(dāng)采用并發(fā)回收算法的時(shí)候,一般對(duì)于老年代區(qū)域,不會(huì)等待內(nèi)存小于10%左右的時(shí)候才會(huì)發(fā)起回收,因?yàn)椴l(fā)回收是允許在回收的時(shí)候被分配,那樣就有可能來不及了,所以并發(fā)回收的時(shí)候,JVM可能會(huì)在68%左右的時(shí)候就開始啟動(dòng)對(duì)老年代GC了。

???d)并行回收:并行回收指利用多個(gè)CPU對(duì)JVM進(jìn)行并行垃圾回收的過程,并行度都是可以設(shè)置的,可以分別對(duì)年輕代和老年代配置是否使用并行回收。

?

好了,回收算法就說到這里,那么如何利用好回收算法,在看了上面的介紹后,是否對(duì)JVM有了一個(gè)大致的了解,具體細(xì)節(jié),可以慢慢實(shí)踐,在文章最后給出一些常用的java虛擬機(jī)內(nèi)存設(shè)置參數(shù)的說明,不過并不權(quán)威,需要根據(jù)實(shí)際情況而定才可以。

?

?

?

?

下面說下java虛擬機(jī)除了消耗基本內(nèi)存外還會(huì)消耗什么內(nèi)存?

?

?

?

4、JVM占用的空間除HeapSize還會(huì)占用什么?

?

?

??? 一般來說,對(duì)于很多學(xué)了好幾年,甚至于很多年java人來說,一旦看到OutOfMemeory(簡(jiǎn)稱OOM),就認(rèn)為HeapSize不夠,然后瘋狂的增加-Xmx的值,但是HeapSize只是其中一個(gè)部分,當(dāng)你去做一個(gè)實(shí)驗(yàn),也就是java啟動(dòng)時(shí)直接在程序中瘋狂的new 一些線程出來,直到內(nèi)存溢出,當(dāng)-Xms -Xmx設(shè)置得越大的時(shí)候,得到的線程個(gè)數(shù)會(huì)越少,為什么呢?因?yàn)镺OM并不是HeapSize不夠而導(dǎo)致的,而由很多種情況。

?

??? 首先看下操作系統(tǒng)如何劃分內(nèi)存給應(yīng)用系統(tǒng),其實(shí)在Win 32、Linux 32的系統(tǒng)中,地址總線為32位的理論上應(yīng)該可以支持4G內(nèi)存空間,但是當(dāng)你在Win 32上設(shè)置初始化內(nèi)存如果達(dá)到2G,就會(huì)報(bào)錯(cuò),說這個(gè)塊空間沒法做,首先默認(rèn)的Win32系統(tǒng),會(huì)按照50%比例給予給Kernel使用,而另一部分給應(yīng)用內(nèi)存,也就是說操作系統(tǒng)內(nèi)核部分不論是否使用,這一半是不會(huì)給你的,而還有2G呢,它在系統(tǒng)擴(kuò)展的部分,也就是并非Kernel的部分,有很多靜態(tài)區(qū)域和字典表的內(nèi)容,所以要?jiǎng)澐忠粋€(gè)連續(xù)的2G內(nèi)存給JVM在Win 32上是不可能的,Win 32提出了一種Win 32 3G模式,貌似可以劃分3G空間,其實(shí)它只是將內(nèi)核部分縮小也就是管理部分縮小,也就是將一部分劃分到外部來使用,而且Win 32習(xí)慣在內(nèi)存2G的位置做一些手腳,讓你分配連續(xù)2G沒有可能性,一般來說在Win 32平臺(tái)上,在物理內(nèi)存足夠的情況下給JVM劃分的空間一般是1.4~1.5G左右,具體數(shù)據(jù)沒有測(cè)試過;而Linux 32類似于Win 32 3G模式,但是它還是一般情況下分布不凌亂的情況下,一般可以給JVM劃分到2G的大小。Linux 32 Hugemem是一個(gè)擴(kuò)展版本,可以劃分更大的空間,但是需要付出一些其他的代價(jià),理論上可以支持到4G給應(yīng)用,也就是Kenel是獨(dú)立的;Solaris x86-32和AIX 32等系統(tǒng),也類似于Linux 32平臺(tái)一樣。

?

??為什么還要預(yù)留一些空間出來呢?這些空間給誰?

? 當(dāng)你申請(qǐng)一個(gè)線程的時(shí)候,它的除了線程內(nèi)部對(duì)象的開銷外,線程本身的開銷,是需要OS來調(diào)度完成,一般來說,會(huì)在OS的線程與虛擬機(jī)內(nèi)部有都有一個(gè)一一對(duì)應(yīng)的,但是會(huì)根據(jù)操作系統(tǒng)不同有所變化,有些可能只有一個(gè),總之heapSize外的那部分空間是跑不掉的,它放在哪里呢?就是放在Stack中的,所以上文中的-Xss就是設(shè)置這個(gè)的,在jdk 1.5以后,每個(gè)線程的大小被默認(rèn)設(shè)置為1M的stack開銷,我們習(xí)慣將這個(gè)開銷降低。

?

??好了知道了指針、線程是在heapSize外部的,還有什么呢?

? 當(dāng)你自己使用native方法,也就是JNI的時(shí)候,調(diào)用本地其他語言,如C、C++在程序中使用了malloc等類似方法開辟的內(nèi)存,都不是在heapSize中的,而是在本地OS所掌控的,另外這部分空間如果沒有相應(yīng)的釋放命令,就需要在對(duì)應(yīng)finalize方法內(nèi)部調(diào)用其他的native方法來完成對(duì)相應(yīng)對(duì)象的釋放,否則這部分將成為OS級(jí)別的內(nèi)存泄露,直到JVM進(jìn)程重啟或者宕機(jī)為止(操作系統(tǒng)會(huì)記錄下進(jìn)程和相應(yīng)線程和堆內(nèi)存的關(guān)聯(lián)關(guān)系,但是進(jìn)程再?zèng)]有釋放前,OS也是不會(huì)回收這部分內(nèi)存的)。

??另外在使用JavaNIO以及JDBC、流等系列操作時(shí),當(dāng)形成與終端交互時(shí),會(huì)在另一個(gè)位置形成一個(gè)內(nèi)存區(qū)域,這些內(nèi)存區(qū)域都不在HeapSize中。

? 所以常見的OOM現(xiàn)象有以下幾種:

? 1、heapSize溢出,這個(gè)需要設(shè)置Java虛擬機(jī)的內(nèi)存情況

? 2、PermSize溢出,需要設(shè)置Perm相關(guān)參數(shù)以及檢查內(nèi)存中的常量情況。

? 3、OS地址空間不夠,也就是沒有那么多內(nèi)存分配,這個(gè)一般是啟動(dòng)時(shí)報(bào)錯(cuò)。

? 4、Swap空間頻繁交互,進(jìn)程直接被crash掉,在不同操作系統(tǒng)中會(huì)體現(xiàn)不同的情況。

? 5、native Thread溢出,注意線程Stack的大小,以及本身操作系統(tǒng)的限制。

??6、DirectByteBuffer溢出,這一類一般是在做一些NIO操作的時(shí)候,或在某種情況下使用ByteBuffer,在分配內(nèi)存時(shí)使用了allocateDirect以及使用一些框架間接調(diào)用了類似方法,導(dǎo)致直接內(nèi)存的分配(如mina中使用IoByte去調(diào)用,當(dāng)參數(shù)設(shè)置為true的時(shí)候就分配為直接內(nèi)存,所謂直接內(nèi)存就是又OS定義的內(nèi)存,而不需要從程序間接拷貝一次再輸出的過程,提高性能,但是如果沒有手動(dòng)回收是回收不掉的),導(dǎo)致的Buffer問題,如輸出大量的內(nèi)容,輸入大量的內(nèi)容,此時(shí)需要盡量去嘗試限制它的大小。

?

使用非常多的工具區(qū)檢測(cè)Java的內(nèi)存如:jstat(只能看HeapSize和PermSize)、jmap(很細(xì)的東西)、jps(java的ps -ef呵呵)、jdb(這個(gè)不是監(jiān)控工具哈,這個(gè)是debug工具)、jprofile(圖形支持,但是可以遠(yuǎn)程連接)等等;jconsole(可以看到heapsize、permsize+native mem size(這這里叫做:non-heapsize)等等的使用的趨勢(shì)圖)、visualvm(極為推薦的東西,圖形化查看,你可以查看到內(nèi)存單元分配、交換、回收、移動(dòng)等等整個(gè)過程,非常清晰展現(xiàn)jvm的全局資源)、另外pmap可以展現(xiàn)非常清晰的資料,可以精確到某一個(gè)java進(jìn)程內(nèi)部的每一個(gè)細(xì)節(jié),而且可以看到heapsize只是其中很小一部分(在solaris操作系統(tǒng)上看得最齊全,LINUX下有些進(jìn)程可能看不太懂);也可以在/proc/進(jìn)程號(hào)/maps中查看(這里可以看到內(nèi)存地址單元的起始地址,包含了reserved的地址范圍和commited的地址范圍),全局資源使用操作系統(tǒng)top命令和free命令看;IBM有一個(gè)GCMV免費(fèi)下載工具也很好;Win32有一個(gè)WMMap工具都是很好的工具

?

?

使用相應(yīng)的工具觀察相應(yīng)的內(nèi)容,當(dāng)觀察到內(nèi)存的使用從無到有,上升,然后處于一個(gè)平穩(wěn)趨勢(shì),那么這個(gè)JVM應(yīng)該是較為穩(wěn)定的;如果發(fā)現(xiàn)它經(jīng)過一段平滑期后,又出現(xiàn)飆升,這個(gè)必然是有問題的,至于什么問題,根據(jù)前面的學(xué)下和實(shí)際情況我們可以去分析;當(dāng)它開始后,平滑過程,出現(xiàn)緩慢上升的過程,但是始終會(huì)上升到極點(diǎn),那么一個(gè)是需要知道物理內(nèi)存時(shí)候可用,另一個(gè)就是少量的內(nèi)存泄露(JVM現(xiàn)代也有內(nèi)存泄露,只是它的內(nèi)存泄露并非C、C++中的內(nèi)存泄露)。

?

5、糾正錯(cuò)誤:intern()的使用上的錯(cuò)誤

???? 最后一章節(jié),我自己糾正一下我自己的錯(cuò)誤,以前的文章中,也就是關(guān)于intern的使用,最近對(duì)他做了一些深入研究,因?yàn)橐郧耙彩呛秃芏嗤瑢W(xué)一樣,聽到別人推薦什么就瘋狂的使用,知道點(diǎn)原理也是點(diǎn)大概,沒有深入研究?jī)?nèi)部的內(nèi)容。

???? 我曾經(jīng)在文章中說到任何系統(tǒng)最多使用的數(shù)據(jù)類型必然是String,不管做什么,所以在String的處理上很有研究,推薦使用java的朋友在大量使用對(duì)比的時(shí)候不要用equals,而推薦使用intern(),但是我最近發(fā)現(xiàn)我錯(cuò)了,我這里給大家道歉,因?yàn)榭赡軙?huì)誤導(dǎo)很多朋友;下面說明下這個(gè)東西為什么?

???? 首先我開始自己懷疑自己的時(shí)候是想說,如果intern可以做到高效,那么equals是不是在String中就沒有存在的必要了呢,當(dāng)時(shí)對(duì)于我理解僅僅為常量池的一個(gè)地址對(duì)比,好比是兩個(gè)數(shù)字的compare,僅僅需要CPU的單個(gè)指令即可完成;于是我開始做了兩個(gè)實(shí)驗(yàn),一個(gè)是最原始,最初級(jí)的方法采用單線程循環(huán)1000000次調(diào)用equals與intern等值對(duì)比,并且采用了不同長(zhǎng)度的字符串去做比較,發(fā)現(xiàn)equals竟然比intern要快,而且隨著字符串長(zhǎng)度的增加,equals會(huì)明顯快與intern,然后使用多線程測(cè)試也是得到一樣的效果,我首先很不敢相信自己堅(jiān)持的理論被徹底和諧了,后來冷靜下來必須需要面對(duì),通過很多權(quán)威資料的閱讀,我發(fā)現(xiàn)我對(duì)JVM常量池的理解還只是一點(diǎn)點(diǎn)皮毛而已,所以我做了更加深入的研究。

??? 原來intern方法被調(diào)用時(shí)是在Perm中的String私有化常量池中尋找相應(yīng)的內(nèi)容,而尋找雖然可以通過hash定位到某些較小的鏈表中,但是還是需要在鏈表中逐個(gè)對(duì)比,對(duì)比的方法仍然是equals,也就是拋開hash的開銷,intern最少要與里面的0到多個(gè)對(duì)象進(jìn)行equals操作,而且如果不存在,還要在常量池開辟一塊空間來記錄,如果存在則返回地址,也就是常量池保證每個(gè)String常量是唯一的,這個(gè)開銷當(dāng)然大了,而且如果使用在業(yè)務(wù)代碼中將會(huì)導(dǎo)致Perm區(qū)域的不斷增加;

??? 于是,我又反過來想了:既然equals比他效率高,為啥還要用intern呢?而且equals的那個(gè)算法對(duì)于長(zhǎng)字符串逐個(gè)字符對(duì)比的過程我實(shí)在是難以入目;而且也實(shí)在是覺得不甘心自己的理論就這么容易被和諧掉,因?yàn)樽约阂呀?jīng)在不少程序中這樣用過,這樣我豈不是犯下大錯(cuò)了,因?yàn)樽约簠⑴c過的項(xiàng)目的確太多了,而且有類似的代碼我寫入了框架中,最終發(fā)現(xiàn)我可能錯(cuò)了一半,也就是歷史上的記錄可能我有一半類似的代碼是錯(cuò)誤的;為什么呢?intern還是有用的,我先做了一個(gè)測(cè)試,那就是,用一個(gè)已經(jīng)intern好的對(duì)象,讓他與一個(gè)常量做等值,循環(huán)次數(shù)和上面一樣,結(jié)果我預(yù)料的結(jié)果發(fā)生了,那就是比equals快出了N多倍數(shù),隨著長(zhǎng)度的增加,會(huì)體現(xiàn)出更加明顯的優(yōu)勢(shì),因?yàn)閕ntern對(duì)比的始終是地址,和長(zhǎng)度無關(guān),于是我想到了如何使用它,就是在程序中返回通過字符串類似于數(shù)字一樣的類型判定時(shí),如:做一個(gè)sqlparser的時(shí)候,經(jīng)常根據(jù)數(shù)據(jù)類型做不同的動(dòng)作,這樣如果用equals會(huì)在每次循環(huán)時(shí)付出很多開銷,尤其是很多數(shù)據(jù)庫的類型非常多,最壞的是從上到下每個(gè)字符串匹配一次,當(dāng)然長(zhǎng)度不等開銷很小,長(zhǎng)度相等開銷就大了;intern我就將這些schema信息預(yù)先intern掉,也就是他們已經(jīng)指向了常量池,當(dāng)再真正匹配時(shí),就不需要用intern了,而是直接匹配,也就是將這個(gè)開銷放在初始化的過程中,運(yùn)行時(shí)我們不去增加它的開銷。

??? 所以,個(gè)人是犯下一個(gè)錯(cuò)誤,并且以前還很張揚(yáng)的到處宣傳,呵呵,現(xiàn)在覺得有點(diǎn)傻,希望在看到某些推薦用什么新東西的時(shí)候,千萬不要在沒有研究明白他就去用它,甚至于濫用它,至少要經(jīng)過一些簡(jiǎn)單的測(cè)試,不過對(duì)于現(xiàn)代很多復(fù)雜的東西,一些簡(jiǎn)單的測(cè)試已經(jīng)不足以說明問題,就像Lock與Synchronize的開銷一樣,如果采用簡(jiǎn)單的循環(huán)的話,你會(huì)發(fā)現(xiàn)新版本的Lock的開銷將會(huì)比Synchronized的開銷更加大,它適合的是并發(fā),讀寫的并發(fā),所以真正要弄清楚還是研究?jī)?nèi)在。

?

??? 最后說下,我個(gè)人對(duì)JVM的期望,JVM做到了很多個(gè)板塊之間使用不同的算法,而JVM不希望程序員去關(guān)心內(nèi)存,但是有些特殊的應(yīng)用需要JVM提供多的支持,當(dāng)然有些公司對(duì)JVM內(nèi)核進(jìn)行了改造來適合特殊的應(yīng)用,但是我們更加希望標(biāo)準(zhǔn)的JVM能夠提供更加靈活的內(nèi)存管理機(jī)制,而不僅局限于配置,因?yàn)榕渲眠m中是死的,在很多時(shí)候會(huì)面臨擴(kuò)展性的限制;如很多時(shí)候我們認(rèn)為可以判定很多的對(duì)象本身就是不會(huì)被回收或者根本不容易被回收的,就不用到Y(jié)oung的空間和其他的業(yè)務(wù)套在一起倒騰了;對(duì)于經(jīng)常做page cache的系統(tǒng),而page cache的命中率不是特別高(95%以上就很高),也不是很低(如80%以下),這個(gè)時(shí)候,置換到快不慢的,而會(huì)導(dǎo)致在老年代的回收的頻繁起來,就我個(gè)人希望這些空間都能獨(dú)立出來,甚至于可以由程序去控制和指定,當(dāng)然JVM可以自身去默認(rèn);尤其是按照一些特殊的對(duì)象等級(jí)類型或者說對(duì)象的大小,這些細(xì)節(jié)都可以采用一些相應(yīng)的默認(rèn)GC手段來完成,也可以人工的指定,當(dāng)然也在默認(rèn)情況下可以按照原有的模式進(jìn)行架構(gòu),這樣JVM的內(nèi)存調(diào)節(jié)的靈活將會(huì)更加寬松,使得它能在各類場(chǎng)合下只要使用相對(duì)應(yīng)的手段配置和程序調(diào)整都是可以打到目的的。

?

?? 本文包含大量個(gè)人見解,如有不是之處,請(qǐng)大家多多指教!本文到此完結(jié),內(nèi)容粗而不深入,細(xì)節(jié)問題,細(xì)節(jié)討論。

?

?

?

?

?常見參數(shù)JVM參數(shù)配置(java vm Hotspot TM 1.6):

?

?-Xms為初始化為HeapSize的空間,即被Commited的尺寸。 ?-Xmx為最大的HeapSize空間,有些尚未被Commited,但是已經(jīng)被進(jìn)程所Reserved,當(dāng)現(xiàn)在已經(jīng)被Commit的空間長(zhǎng)期處于(jdk1.1還有一個(gè)-mx為包含handler表的空間) ?-Xmn設(shè)置Young的空間大小,此時(shí)NewSizeMaxNewSize一致,或者分別設(shè)置-XX:NewSize=128m ?-XX:PermSize?= 64M-XX:MaxPermSize= 64M為永久代的初始大小和最大大小。 ?-XX:NewRatio= 3?為Tenured:Young的初始尺寸比例(設(shè)置了大小就不再設(shè)置此值),此時(shí)Young占用整個(gè)HeapSize的1/4大小。 ?-XX:SurvivorRatio= 6:為Eden:Survivor比例大小,此時(shí)一個(gè)Survivor占用Young的1/8大小,而Eden占用3/4大小 ?-Xss=256kThreadStack空間大小,jdk?1.5以后默認(rèn)是1M,在IBMjdk中還有-Xoss參數(shù)(此時(shí)每個(gè)線程占用的stack空間為256K大小) ?-XX:MaxTenuringThreshold=3:一般一個(gè)對(duì)象在Young經(jīng)過多少次GC后會(huì)被移動(dòng)到OLD區(qū)。
-XX:+UseParNewGC:對(duì)Yong區(qū)域啟用并行回收算法。
?-XX:+UseParallelGC:一種較老的并行回收算法 ?-XX:+UseParallelOldGC:對(duì)Tenured區(qū)域使用并行回收算法。 ?-XX:ParallelGCThread=10:并行的個(gè)數(shù),一般和CPU個(gè)數(shù)相對(duì)應(yīng)。 ?-XX:+UseAdaptiveSizepollcy:收集器自動(dòng)根據(jù)實(shí)際情況進(jìn)行一些比例以及回收算法調(diào)整。 ?-XX:CMSFullGCsBeforeCompaction= 3:多少次GC后會(huì)進(jìn)行壓縮碎片 ?-XX:+UseCmsFullCompactAtFullCollction:打開老年代壓縮 以下3個(gè)參數(shù)為永久帶回收參數(shù):
-XX:+UseConcMarkSweepGC?-XX:+CMSClassUnloadingEnabled

-XX:+CMSPermGenSweepingEnabled對(duì)永久帶進(jìn)行相應(yīng)的回收,在jdk1.6中不需要數(shù):-XX:+CMSPermGenSweepingEnabled -XX:MinHeapFreeRatio這是指剩余空間百分比多少時(shí),開始減小commited的內(nèi)存; -XX:MaxHeapFreeRatio指剩余空間百分比多少時(shí),開始增加commited的內(nèi)存,直到-Xmx大小。 -XX:MaxGCPauseMillis指GC最大的暫停時(shí)間,當(dāng)超過這個(gè)時(shí)間,那么JVM會(huì)適當(dāng)調(diào)整內(nèi)存比例(前提是使用的是基于比例的YONG和設(shè)置)。 -XX:+UseConcMarkSweepGC?啟動(dòng)并發(fā)GC,一般針對(duì)Tenured區(qū)域。 -XX:+CMSIncrementalMode增量GC,將內(nèi)存切塊,分布在多個(gè)局部去GC。 -XX:CMSInitiatingOccupancyFraction在并發(fā)GC下,由于一邊使用,一遍GC,就不能在不夠用的時(shí)候GC,默認(rèn)情況下是在使用了68%的時(shí)候進(jìn)行GC,通過該參數(shù)可以調(diào)整實(shí)際的值。
大致的參數(shù)設(shè)置就這些,但是GC本身的參數(shù)還有很多,尤其是和應(yīng)用或者和具體硬件結(jié)合起來的時(shí)候,而BEA和IBM也有自己的JDK,這里有些參數(shù)他們支持,有些參數(shù)不支持,在某些平臺(tái)和甚至于硬件上可以支持特殊的參數(shù)來控制(如在部分intel系列的多CPU機(jī)器上,通過它的NUMA架構(gòu),可以設(shè)置對(duì)應(yīng)參數(shù)支撐,節(jié)點(diǎn)和CPU之間可以實(shí)現(xiàn)分工負(fù)載、常規(guī)服務(wù)上都是SMP的,而大型機(jī)上多半是MPP);類似于上面的并發(fā)GC在一般情況下是不會(huì)進(jìn)行compact壓縮的,因?yàn)樗M厥盏臅r(shí)間短,但是充滿compact的壓縮時(shí)間必然不是那么短,所以在部分特殊應(yīng)用下有些使用定寬度的內(nèi)存尺寸,回收后不管空余內(nèi)存,因?yàn)槊總€(gè)內(nèi)存的尺寸都是那么大,這樣來處理,當(dāng)然這樣必然會(huì)導(dǎo)致很多的內(nèi)存浪費(fèi),但是它的好處是可以沒有compact而不存在說要分配的內(nèi)存分配不到的問題。

總結(jié)

以上是生活随笔為你收集整理的认识JVM--第一篇-对象分配回收算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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

天天鲁一鲁摸一摸爽一爽 | 2021国产精品 | 国产在线专区 | 国产视频在线播放 | 在线视频 影院 | 99精品国产99久久久久久福利 | 99久久99久久精品 | 看片的网址 | 日韩成人免费电影 | 丁香资源影视免费观看 | 超碰在线人人97 | 五月天色综合 | 欧美日韩精品免费观看视频 | 天天艹| a资源在线 | 97国产情侣爱久久免费观看 | 久久永久免费 | 超碰精品在线 | 日韩在线视频播放 | 人人擦 | 久久精品激情 | 精品国产三级a∨在线欧美 免费一级片在线观看 | 成人毛片在线观看 | 美女网站视频色 | 97超碰色偷偷| 99产精品成人啪免费网站 | 91视频免费播放 | 日韩视频一区二区三区 | 五月黄色| 天堂在线一区 | 日韩色综合网 | 国产亚洲精品久久网站 | 亚洲免费专区 | 日日操网 | 91香蕉视频在线 | 精品高清视频 | av高清网站在线观看 | 黄色www在线观看 | 人人干人人做 | 探花在线观看 | 欧美另类xxx | 久久九九久久九九 | 国产免费xvideos视频入口 | 国产不卡在线视频 | 国产中文字幕免费 | 午夜黄色影院 | 99精品国产兔费观看久久99 | 丁香花中文在线免费观看 | 91九色精品 | 最新av在线免费观看 | 国产精品久久久久一区二区国产 | 欧美精彩视频在线观看 | 激情久久综合网 | 超碰97在线人人 | 婷婷视频在线 | 亚洲不卡123 | 国产成a人亚洲精v品在线观看 | 国产高清在线看 | 香蕉影院在线观看 | 四虎海外影库www4hu | 精品国内自产拍在线观看视频 | 久久理伦片 | 久久久久久久久久毛片 | 久久超| 最新国产精品视频 | 激情综合色综合久久综合 | 色婷婷亚洲 | 91成人免费电影 | 国产黄色资源 | 国产成人免费在线观看 | 黄色tv视频 | 超碰国产97 | 日色在线视频 | 国产视频中文字幕在线观看 | 精品爱爱| 亚洲精品国偷拍自产在线观看蜜桃 | 久久影院中文字幕 | 国产成人精品一区在线 | 三级av在线免费观看 | 久久夜靖品 | 狠狠色丁香久久婷婷综合五月 | 日韩欧美高清不卡 | 国产精品v欧美精品 | 97超碰人人澡人人爱学生 | 久久久久女人精品毛片九一 | 2023国产精品自产拍在线观看 | 在线国产激情视频 | 国产不卡毛片 | 中国一级片在线观看 | 日韩视频免费观看高清 | 久久国产网站 | 国产自产在线视频 | 亚洲性少妇性猛交wwww乱大交 | 欧美日韩另类视频 | 少妇高潮流白浆在线观看 | 一区二区三区 亚洲 | 国产婷婷vvvv激情久 | 久久久久久久久久久高潮一区二区 | 999国产精品视频 | 福利一区在线视频 | 中文在线免费视频 | av网站在线观看免费 | 中文字幕永久 | 日韩久久午夜一级啪啪 | 视频在线观看入口黄最新永久免费国产 | 欧美福利网站 | 成人毛片100免费观看 | 久久一级片 | 久久综合狠狠综合久久狠狠色综合 | 韩日在线一区 | 97色国产| 国产精品ⅴa有声小说 | 国产久草在线观看 | 免费观看91 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 成人黄在线观看 | 手机看国产毛片 | 黄色a大片 | 中字幕视频在线永久在线观看免费 | 四虎成人网 | 久久精品成人欧美大片古装 | 在线视频 区 | av日韩国产 | 一级特黄aaa大片在线观看 | 国产精品久久久久久久午夜片 | 亚洲涩综合 | 日韩免费一级a毛片在线播放一级 | 久久精品一区二区三区四区 | 99精品国产在热久久下载 | 国产做a爱一级久久 | 国产精品久久久久三级 | 欧美精品乱码99久久影院 | 免费在线观看av网址 | 亚洲在线视频免费观看 | 国产91精品久久久久久 | av福利在线看 | 99久久这里只有精品 | 免费看黄色毛片 | 日韩精品首页 | av网站有哪些 | 色福利网 | 91中文字幕| 免费91在线观看 | 久久久在线观看 | 国产小视频在线免费观看视频 | 亚洲作爱| 欧美激情综合五月色丁香 | 天天操狠狠操 | 欧美一级片播放 | 欧美一区二区三区不卡 | 色综合婷婷 | 国产精品精品久久久 | 午夜成人免费电影 | 成人啪啪18免费游戏链接 | 丝袜美女在线观看 | 亚洲天堂精品视频在线观看 | 一区二区三区在线观看 | 日日夜夜91 | 中文字幕乱码一区二区 | 欧美日韩国产一二三区 | 亚洲精品乱码久久久久久蜜桃欧美 | 成人免费视频播放 | 亚洲人av免费网站 | 国产精品 9999| 91视频免费 | 久热久草 | 成av人电影| 日韩视频免费观看高清完整版在线 | 中国一区二区视频 | 国产精品乱码高清在线看 | 丝袜一区在线 | a视频在线播放 | 精品影院一区二区久久久 | 亚洲成a人片在线www | 欧美午夜精品久久久久 | av在线播放一区二区三区 | h视频在线看 | 在线一区二区三区 | 中文字幕乱偷在线 | 四虎在线视频免费观看 | 97综合视频| 国产在线日韩 | 久久深夜福利免费观看 | 久久久免费精品 | 日本黄色大片免费看 | 午夜神马福利 | 久久久久亚洲精品国产 | 欧美视屏一区二区 | 337p欧美| 日本精品va在线观看 | 97国产精品亚洲精品 | 久久免费中文视频 | 日韩在线观看视频免费 | 伊人亚洲综合网 | 91精品国产99久久久久 | 久久免费在线观看 | 又爽又黄又无遮挡网站动态图 | 黄色com| 成人av影视在线 | 狠狠色丁香久久婷婷综合五月 | 亚洲精品99久久久久中文字幕 | 日韩国产精品一区 | 国产一区二区高清 | 国产在线视频一区 | 国产一区二区久久精品 | 国产一区二区播放 | 亚洲激情小视频 | 婷婷精品视频 | 国产精品美女免费 | 一级黄色大片在线观看 | 免费在线观看污网站 | 天天做日日做天天爽视频免费 | 久久久久免费精品视频 | 国产精品高潮呻吟久久av无 | 精品在线观 | 欧美色图亚洲图片 | www.99热精品 | 久久久夜色 | 国产精品视频永久免费播放 | 波多野结衣精品视频 | 日韩夜夜爽| 久久综合狠狠综合 | 免费在线看成人av | 亚洲精品一区二区在线观看 | 免费观看黄色12片一级视频 | 成人蜜桃 | 99视频在线精品国自产拍免费观看 | 免费在线观看成人av | 国产一区二区久久久 | 青草视频免费观看 | 欧美日韩免费视频 | 久久精品亚洲综合专区 | 黄色大片国产 | 五月婷婷激情综合 | 亚洲国产精品一区二区久久,亚洲午夜 | 亚洲深夜影院 | 天天干天天操天天爱 | 国产一级一片免费播放放a 一区二区三区国产欧美 | 国产视频欧美视频 | 91桃色在线播放 | 天天摸日日摸人人看 | 一级欧美日韩 | 一区二区三区在线免费播放 | 2021国产精品视频 | 中国黄色一级大片 | 午夜在线观看 | 99r国产精品 | 亚洲精品在线视频播放 | 国产69精品久久久久99 | 在线观看亚洲精品视频 | 中文字幕在线观看第一区 | 成人一级片视频 | 国产精品video爽爽爽爽 | 日日夜夜国产 | 91系列在线观看 | 日韩中文字幕视频在线 | 亚洲精品乱码久久久久久蜜桃不爽 | 在线观看视频你懂的 | 伊人五月天综合 | 日韩.com | 精品日韩在线 | 婷婷精品国产一区二区三区日韩 | 人人射人人澡 | 精品国产区 | 手机版av在线 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 亚洲韩国一区二区三区 | 91九色性视频 | 亚洲精品视频免费 | 久久精品视频观看 | 少妇bbb搡bbbb搡bbbb | 日韩美在线 | 国产亚洲婷婷 | 中文字幕在线免费观看 | 三上悠亚一区二区在线观看 | 日韩三级成人 | 日韩视频精品在线 | 国内一区二区视频 | 免费av网站在线看 | 狠狠干我 | 国产精品免费观看国产网曝瓜 | 在线黄色免费av | 国产精彩视频一区 | 亚洲97在线| 黄色在线观看网站 | 久热国产视频 | 五月婷婷欧美视频 | 高清av网| 婷婷色 亚洲 | 色人久久 | 碰超在线 | 手机看片1042 | 91黄在线看 | 久久久久久久久久免费视频 | av中文字幕在线免费观看 | 黄色在线观看污 | 精品久久久成人 | 国产亚洲精品久久久网站好莱 | 日产乱码一二三区别在线 | 午夜 在线 | 97超碰在线久草超碰在线观看 | 欧美激情综合五月色丁香小说 | 又黄又刺激视频 | 久久综合九色综合欧美就去吻 | 天天激情综合网 | 色妞色视频一区二区三区四区 | 97超碰色偷偷 | 成人作爱视频 | 日本特黄一级片 | 欧美日韩国产一二三区 | 精品福利片 | 69精品在线| a级国产乱理论片在线观看 特级毛片在线观看 | 国产精品精品国产婷婷这里av | 久久99热精品这里久久精品 | 免费成人av网站 | 久久美女视频 | 在线播放你懂 | 成人黄大片 | 亚洲精品国产麻豆 | 99精品国产在热久久 | 亚洲午夜精品一区 | 久久精品伊人 | 99九九热只有国产精品 | 精品国产一区二区三区久久久蜜臀 | 韩国在线一区 | 黄色片亚洲 | 亚洲精品播放 | 成人av观看 | 在线观看中文字幕 | 日韩中文字幕一区 | 亚洲精品国产片 | 国产成人黄色av | 99热精品久久 | 亚洲精品456在线播放乱码 | 久久亚洲精品电影 | 东方av免费在线观看 | 玖玖视频免费在线 | 精品视频999 | 人人澡人人模 | 天堂av在线网址 | 亚洲综合网 | 日韩av不卡在线播放 | 久久久久久久久久久黄色 | 在线观看成人网 | 日韩中文字幕a | 亚洲欧洲一区二区在线观看 | 国产精品99视频 | 国产视频在线播放 | 国产精品激情偷乱一区二区∴ | 手机成人av| 成人夜晚看av | 久久久久久黄色 | 五月开心六月伊人色婷婷 | 91日韩在线专区 | 久久天天躁 | 久久人人爽人人爽人人 | 日日添夜夜添 | 成 人 黄 色 视频免费播放 | 麻豆网站免费观看 | 在线va视频 | 久久久久久电影 | 伊人久久一区 | 一本色道久久综合亚洲二区三区 | 色婷婷av国产精品 | 久久久免费观看视频 | 88av视频 | 五月婷婷丁香色 | 日韩a在线观看 | 国产分类视频 | 欧美成人在线网站 | 人人精久 | 国产成人福利在线观看 | 又黄又爽又刺激的视频 | 亚洲视频大全 | 久久黄页 | 欧美精品在线观看免费 | 亚州视频在线 | 日韩黄色在线电影 | 欧美性高跟鞋xxxxhd | 日本久久久久久 | 亚洲精品系列 | 麻豆一精品传二传媒短视频 | 亚洲国产网站 | 国产资源在线视频 | 欧美天天综合 | 2019精品手机国产品在线 | 欧美日韩在线免费观看视频 | 91精品视频一区 | 在线观看视频三级 | 国产精品久久久久久一区二区 | 欧美日韩久| 日韩高清在线一区二区三区 | 99精品视频99 | 人人超碰免费 | 成人久久免费 | 国产日本高清 | 国产精品成人av久久 | 国产精品美乳一区二区免费 | 美女国内精品自产拍在线播放 | 亚洲女人天堂成人av在线 | 国产专区免费 | 黄色av网站在线免费观看 | 亚洲1区在线 | 夜色成人av | 曰韩精品| 国产精品久久久久9999 | 国产精品99精品久久免费 | 国产在线观看不卡 | 国产精品久久久久久99 | 午夜久久久久久久 | 91在线网址 | 国产日韩欧美在线一区 | 日韩免费观看一区二区 | 亚洲一区二区精品在线 | 黄色的片子| av在线网站观看 | 91亚色视频在线观看 | 日韩av在线资源 | 99在线国产| 日韩99热| 97国产小视频 | 国产午夜精品福利视频 | 激情婷婷亚洲 | 亚洲国产成人精品在线观看 | 中文字幕黄色网址 | 国产精品高清免费在线观看 | 91精品999| 在线性视频日韩欧美 | 狠狠干天天 | 亚洲欧美国产日韩在线观看 | 欧美黄网站| 99麻豆视频 | 亚洲精品黄色片 | 五月激情片 | 国产一区二区免费在线观看 | 丁香伊人网 | 国产午夜在线观看视频 | 96精品高清视频在线观看软件特色 | 亚洲粉嫩av | 国产 色 | 国产午夜小视频 | 狠狠操在线| 精品国产乱子伦一区二区 | 日韩免费二区 | 九九九九热精品免费视频点播观看 | 五月激情久久 | 中文字幕日韩一区二区三区不卡 | 丁香久久激情 | 精品国产一区二区三区久久久蜜臀 | 国产免费视频一区二区裸体 | 中文有码在线 | 欧美日韩在线播放 | 国产精久久久 | 夜夜天天干 | 天堂在线一区 | 国产手机视频在线观看 | 毛片网站在线 | 久久亚洲精品电影 | 久久精品一区二区国产 | 视频福利在线 | 中文字幕综合在线 | 热re99久久精品国产99热 | 91麻豆精品国产 | 天天激情天天干 | 国产一区二区在线免费播放 | 中文视频在线播放 | 999视频精品 | av网站地址| 深夜男人影院 | 成人一区二区三区在线观看 | 中文字幕一区在线观看视频 | 日韩特级片 | 亚洲高清在线视频 | 97视频在线观看视频免费视频 | 成人电影毛片 | 亚洲精品18日本一区app | 中文字幕在线观看视频网站 | 91精品国产三级a在线观看 | 91在线看免费 | 99热国内精品 | 久久久国产在线视频 | 免费观看高清 | 国产手机视频在线播放 | 在线观看中文 | av福利在线 | 狠狠色丁香久久综合网 | 国产精品美女久久久久久免费 | 蜜桃视频在线观看一区 | 国产在线超碰 | 99久久精品免费看国产麻豆 | 久久免视频| 99热在线这里只有精品 | 91插插视频 | 天天干天天操天天干 | 激情五月看片 | 婷婷四房综合激情五月 | 日韩不卡高清视频 | www.香蕉视频在线观看 | 999久久久精品视频 日韩高清www | 国产欧美在线一区二区三区 | 一区精品在线 | 婷婷中文在线 | 日韩欧美精品在线观看 | 欧美一级片在线播放 | 日韩精品一区二区三区电影 | 啪啪免费视频网站 | 国产精品第54页 | av一级片在线观看 | 国产无遮挡又黄又爽在线观看 | 久久国产经典视频 | 黄色小说视频在线 | 在线观看激情av | 免费在线观看视频一区 | 在线观看一区二区精品 | 亚洲九九九在线观看 | 亚洲 欧洲 国产 精品 | 特黄免费av | 伊人久久一区 | 亚洲视频综合在线 | 欧美激情综合五月色丁香 | 国产精品欧美久久久久天天影视 | 国产精品久久久久久久久久三级 | 99精品久久只有精品 | 欧洲视频一区 | 国产日韩欧美精品在线观看 | 国产一区二区在线播放视频 | 92中文资源在线 | 久久久久欠精品国产毛片国产毛生 | 国产精品久久久久久69 | 国产精品99久久久久久久久久久久 | 伊人久久国产 | 色婷婷www| 中文字幕在线一区二区三区 | 成人av资源网站 | 日韩激情视频 | a级片韩国 | 国产精品久久久久久69 | 天天操天天摸天天爽 | 久草视频一区 | 亚洲国产精品va在线 | 99c视频在线 | 在线成人av | 日韩国产精品久久 | 99久久久国产精品免费99 | 国产视频导航 | 四虎国产 | 久草免费新视频 | 国产精品日韩高清 | 久久精品免费电影 | 精品久久久久久综合 | 日韩免费av在线 | 在线中文字幕电影 | 精品久久久久_ | 天天操夜操 | 日韩精品首页 | 超碰97免费观看 | 久久久久麻豆v国产 | 人人干在线 | 欧美成人h版在线观看 | 91精品国产一区 | 中文字幕日韩一区二区三区不卡 | 天天射天天射天天射 | 亚洲国产三级在线观看 | 久久精品美女视频网站 | 亚洲精品ww | 成人av资源网站 | 天天色天天搞 | 五月天婷亚洲天综合网精品偷 | 在线观看a视频 | 日韩国产精品久久久久久亚洲 | 欧美精品久久久久久久久老牛影院 | 亚洲午夜久久久久久久久久久 | 婷婷夜夜| 成人av av在线 | 国产精品久久久久久电影 | 97超碰在线人人 | 国产一区二区在线免费播放 | 在线а√天堂中文官网 | 丁香在线 | 色资源网免费观看视频 | 91精品免费看 | 国产精品99久久久久的智能播放 | 五月婷婷黄色 | 天天草天天干天天射 | 久久久久久久久久久黄色 | 怡红院成人在线 | 狠狠色丁香婷婷综合视频 | 婷婷在线不卡 | 国产一区二区在线精品 | 日韩中文字幕视频在线观看 | 成年人黄色免费视频 | 久久久久久久久免费视频 | av中文天堂在线 | 黄色三级网站 | 国产vs久久 | 日本三级全黄少妇三2023 | 久久五月激情 | 色综合久久88色综合天天6 | 欧美片网站yy | 日本不卡123区 | 久久三级视频 | 欧美日韩在线视频一区二区 | 一区二区电影网 | 日韩二区三区在线观看 | 射久久久 | 天天干人人插 | 91入口在线观看 | 黄色av电影一级片 | 亚洲理论视频 | 娇妻呻吟一区二区三区 | 亚洲尺码电影av久久 | 免费在线观看视频一区 | 99色免费视频 | 一区二区三区在线免费观看视频 | 中文字幕日韩在线播放 | 日日干夜夜干 | 日日夜夜精品网站 | 日日碰狠狠躁久久躁综合网 | 精品一区二区三区电影 | 国产亚洲无 | 97超碰伊人 | 日韩在线观看一区 | 成年人三级网站 | 国产精品专区一 | 日韩欧美精品在线观看视频 | 国产在线视频一区二区三区 | 中文字幕在线免费97 | 欧美久久久影院 | 一区二精品 | 97超碰在线免费 | 日韩精品专区在线影院重磅 | 国产在线97 | 1000部18岁以下禁看视频 | 精品国产免费看 | 日本视频精品 | 九月婷婷人人澡人人添人人爽 | 免费日韩高清 | 欧美日韩在线网站 | 天天干天天碰 | 综合色狠狠 | 日韩二区三区在线 | 成人av网页| 久青草视频 | 一本一本久久a久久 | 日韩欧美一区二区在线观看 | 99久久网站 | 91亚洲精品乱码久久久久久蜜桃 | 欧美伦理电影一区二区 | 国产精品亚州 | 久久国产精品99精国产 | 国产精品剧情在线亚洲 | 99精品视频免费全部在线 | 精品国产乱码久久久久久1区2匹 | 国产一区视频导航 | 手机成人av | 国产丝袜美腿在线 | 午夜在线日韩 | 免费精品在线观看 | 免费麻豆视频 | 91在线视频网址 | 视频在线99| 日韩欧美成 | 三上悠亚在线免费 | 天天操天天射天天爽 | 国产手机在线视频 | 国产综合精品一区二区三区 | 亚洲欧洲国产日韩精品 | 美女福利视频 | 久久99欧美 | 91污视频在线 | 最新影院| 久久一级电影 | 久久精品一区二区三区国产主播 | 奇米网8888| 久久精品高清 | 亚洲午夜精品福利 | 久久久久久高清 | 91av蜜桃 | 丁香激情综合久久伊人久久 | 日韩视频在线一区 | 欧美一级免费在线 | 99精品福利| 欧美日韩在线精品一区二区 | 一区二区三区免费 | 成人免费在线网 | 免费视频成人 | 999视频网站| 国产高清成人av | 在线免费观看国产 | 欧美日韩高清一区二区三区 | 国产99久久九九精品 | 中文在线资源 | 免费看污网站 | 久久免费播放视频 | 欧美成年人在线视频 | 亚洲一区二区观看 | 五月天堂网 | 在线看一级片 | 99超碰在线观看 | 久久综合色影院 | 国产片免费在线观看视频 | 青青河边草免费直播 | 免费精品视频 | 久久在视频 | a特级毛片 | 日韩理论影院 | 最近最新最好看中文视频 | 亚洲精品国偷拍自产在线观看 | 99精品视频一区二区 | 婷婷丁香狠狠爱 | 久久国语 | 在线观看韩国av | 91视视频在线直接观看在线看网页在线看 | 中文字幕888 | 欧美激情视频一二三区 | 激情欧美一区二区免费视频 | 中文字幕在线观看国产 | 亚洲视频资源在线 | 欧美一二在线 | 久久久久在线 | 91九色网站 | 国产99久久精品一区二区永久免费 | 操一草 | 国产精品久久久999 国产91九色视频 | 日日夜夜91 | 97超碰人人澡人人爱 | 最新免费中文字幕 | av丝袜美腿 | 欧美日韩国产色综合一二三四 | 麻豆视频免费在线播放 | 国产精品美女久久久 | 中文字幕乱码亚洲精品一区 | 狠狠搞,com | 精品久久久久久久久中文字幕 | 国产精品 日韩 欧美 | 在线观看www.| 久久精品79国产精品 | 成人a级大片| 国产一区在线看 | 国产精品视频最多的网站 | 日韩 在线a | 99久久99视频只有精品 | 亚洲精品在线免费观看视频 | 韩国视频一区二区三区 | 国产精品 日韩 | 国产中文字幕视频在线观看 | 亚洲国产成人精品在线观看 | 九九热精品视频在线播放 | 999视频精品 | 麻豆精品视频在线 | 九九免费精品 | 日韩欧美xx| av在线一| 91最新网址 | 在线a人片免费观看视频 | 欧美成人一二区 | 99亚洲精品视频 | 亚洲黄色高清 | 成人午夜影院在线观看 | 成人在线中文字幕 | 久久免费a| 婷婷久月| 久久99久久久久久 | 美女免费视频一区二区 | 国产精品18久久久久白浆 | 国产亚洲婷婷 | 日本中文一级片 | 91精品视频免费观看 | 日韩av伦理片 | 麻豆一区在线观看 | 91日韩免费 | 久草久草久草久草 | 久久69精品久久久久久久电影好 | 亚洲性少妇性猛交wwww乱大交 | 国产手机在线观看 | 中文字幕在线观看免费高清电影 | 久久人人爽视频 | 中文字幕在线看视频国产中文版 | 久久精品亚洲 | 在线看国产视频 | 天天综合久久综合 | 久久视频这里有精品 | 国产91精品在线观看 | 国产99中文字幕 | 免费精品人在线二线三线 | 天天操天天射天天插 | 青青网视频 | 婷婷在线免费观看 | 午夜国产一区二区三区四区 | 999精品在线| 日本女人的性生活视频 | 免费在线观看污 | 国产破处在线播放 | 91在线资源| 亚洲精品中文字幕在线 | 中文在线字幕免费观看 | 亚洲精品97 | 天天爽夜夜爽精品视频婷婷 | 在线视频在线观看 | 亚洲精品视频免费观看 | 麻豆视频91 | 亚洲精品黄色在线观看 | 亚洲成av人片在线观看香蕉 | 久久免费黄色大片 | 欧美黄在线 | 免费高清在线视频一区· | 日本久久久久久久久久 | 亚洲精品国产精品国自产观看 | 久久免费精彩视频 | 久久久久亚洲精品男人的天堂 | 欧美少妇影院 | 久久网页 | 久久99热精品这里久久精品 | 国模吧一区 | 爱色婷婷| 月丁香婷婷| 国产精品自产拍在线观看蜜 | 亚洲成人av影片 | 国产精品久久久久久久久久久免费 | 亚洲三级精品 | 蜜臀av性久久久久蜜臀aⅴ四虎 | 香蕉免费在线 | 中文字幕色在线视频 | 日韩不卡高清 | 成人在线视频你懂的 | 91看毛片| 六月天综合网 | 精品成人国产 | 97国产精品久久 | 久久婷婷丁香 | 国产日韩高清在线 | 97自拍超碰 | 最新99热| 天天操天天干天天干 | 欧美日韩综合在线观看 | 免费在线观看一区二区三区 | 国产精品美女久久久久久免费 | 欧美 亚洲 另类 激情 另类 | 91麻豆精品国产91久久久使用方法 | 国产中文字幕视频在线 | av丝袜美腿 | 天天操天天射天天添 | 在线免费观看亚洲视频 | 日韩视频一区二区 | 国产精品一区二区三区四 | 日韩中文字幕免费在线播放 | 国产精品免费一区二区三区在线观看 | 亚洲专区路线二 | 天天操·夜夜操 | 国产成本人视频在线观看 | 91丨九色丨高潮丰满 | 夜夜嗨av色一区二区不卡 | 国产97在线播放 | 91大神电影 | 国产在线91精品 | 黄色美女免费网站 | 成人免费在线观看入口 | 玖玖在线资源 | 狠狠的操狠狠的干 | 久久香蕉国产 | 久久久久国产精品一区 | 黄色av一区二区 | 亚洲一级性 | 日韩一区二区免费视频 | 在线免费观看黄色 | 手机av电影在线 | 97人人看| 精品久久久久久综合日本 | 欧美三人交 | 国产精品一区二区三区视频免费 | 亚洲欧洲av在线 | 欧美乱淫视频 | 福利视频一区二区 | 午夜精品久久久久久久99水蜜桃 | 亚洲精品国产精品国自产在线 | 国产在线探花 | 操高跟美女 | 97精品伊人 | 精品无人国产偷自产在线 | av超碰免费在线 | 午夜精品久久久久久久99婷婷 | 一区二区三区高清 | 99免费在线观看视频 | 97视频免费在线看 | 91网址在线看 | 中文字幕av在线免费 | 怡红院av久久久久久久 | 波多野结衣久久资源 | 狠狠躁日日躁狂躁夜夜躁av | 日本色小说视频 | av888av.com| 日韩69视频| 欧美中文字幕第一页 | 欧美大片在线观看一区 | 婷婷福利影院 | 国产精品专区一 | 久久久久久久久久久免费视频 | 91成人午夜 | 天天干夜夜夜 | 午夜视频免费 | 国产系列在线观看 | 国产精品岛国久久久久久久久红粉 | 欧美激情视频三区 | 国产精品久久久久久久久久免费 | 国产精品va在线观看入 | 中文字幕韩在线第一页 | 91香蕉视频在线 | 麻豆传媒视频在线播放 | 日日操操操 | 亚洲天堂精品视频 | 国产成人综合图片 | 久久综合久久久久88 | 一区二区三区电影在线播 | 中文字幕日韩精品有码视频 | 91久久精品一区 | 日韩xxxbbb | 精品在线观看一区二区三区 | 久久精品一| 欧美孕妇与黑人孕交 | 亚洲精品免费在线 | 亚洲一区二区视频在线播放 | 狠狠色丁香婷婷 | 九九视频免费 | 日韩 在线观看 | 国产精品久久久久永久免费 | 91丨porny丨九色 | 国产黄色精品网站 | 黄色91免费观看 | 欧美日韩国产亚洲乱码字幕 | 成人国产一区二区 | 九九九在线观看视频 | 日日干美女 | 九九热免费在线视频 | 四虎影视精品成人 | 国产亲近乱来精品 | 午夜色性片| 中文字幕日韩国产 | 97偷拍在线视频 | 亚洲综合五月天 | 96视频免费在线观看 | 精品麻豆 | 99精品国产兔费观看久久99 | 久久久久久久国产精品影院 | 国产涩涩在线观看 | 成人超碰97| 麻豆国产视频 | 亚洲精品福利视频 | a'aaa级片在线观看 | 国产视频丨精品|在线观看 国产精品久久久久久久久久久久午夜 | 黄色在线免费观看网址 | 成人a免费视频 | 成年人精品 | 欧美激情精品久久久 | a在线免费| 91精彩在线视频 | 午夜婷婷综合 | 中文字幕中文字幕在线一区 | 久久亚洲私人国产精品va | 久久久五月婷婷 | 久操久| 国产成人一区二区三区久久精品 | 亚洲全部视频 | 国产成人不卡 | 午夜精品一区二区三区在线观看 | 97久久精品午夜一区二区 | 国产乱视频 | 狠狠狠狠干| 国产成人精品区 | 欧美一级大片在线观看 | 人人网人人爽 | 国产一级二级在线播放 | 激情丁香在线 | 成人一区二区三区在线 | 4438全国亚洲精品观看视频 | 亚洲一级二级三级 | 中文字幕在线电影 | 九九亚洲精品 | 久久久免费在线观看 | 日韩免费一区二区 | 免费成人av | 亚洲免费观看视频 | 婷婷性综合 | 精品视频免费在线 | 91热精品| 中文字幕在线看视频国产 | 日本成人中文字幕在线观看 | 亚洲欧美精品一区 | 中文字幕视频网 | 亚洲午夜精品福利 | 欧美激情视频一区二区三区免费 | 在线观看免费福利 | 婷婷伊人五月 | 成人福利在线播放 | 欧美日韩国产一区二 | 欧美三级高清 | 亚洲精品videossex少妇 | 911精品视频 |