JVM內存結構解析

1. JVM內存結構

(1) JDK1.7的JVM內存結構

JVM內存結構主要有三大塊:堆內存方法區(qū)犯犁。

  • 堆內存是JVM中最大的一塊属愤,由年輕代和老年代組成,而年輕代內存又被分成三部分酸役,Eden空間住诸、From Survivor空間、To Survivor空間涣澡,默認情況下年輕代的這3種空間年輕代按照8:1:1的比例來分配
  • 方法區(qū)存儲類信息贱呐、常量、靜態(tài)變量等數(shù)據(jù)入桂,是線程共享的區(qū)域奄薇,為與Java堆區(qū)分,方法區(qū)還有一個別名Non-Heap(非堆)
  • 棧又分為java虛擬機棧和本地方法棧主要用于方法的執(zhí)行

(2) JDK1.8以后的JVM內存結構


以前的方法區(qū)(或永久代)抗愁,用來存放class馁蒂,Method等元數(shù)據(jù)信息,但在JDK1.8已經沒有了蜘腌,取而代之的是MetaSpace(元空間)沫屡,元空間不在虛擬機里面,而是直接使用本地內存撮珠。

為什么要用元空間代替永久代沮脖?
(1) 類以及方法的信息比較難確定其大小,因此對于永久代的指定比較困難,太小容易導致永久代溢出勺届,太大容易導致老年代溢出绷柒。
(2) 永久代會給GC帶來不需要的復雜度,并且回收效率偏低涮因。
(3) Oracle可能會將HotSpot和Jrockit合二為一。

2. 從更高的一個維度再次來看JVM和系統(tǒng)調用之間的關系

下面我們詳細介紹每個區(qū)域的作用

(1) Java堆(Heap)

對于大多數(shù)應用來說伺绽,Java堆(Java Heap)是Java虛擬機所管理的內存中最大的一塊养泡。Java堆是被所有線程共享的一塊內存區(qū)域,在虛擬機啟動時創(chuàng)建奈应。此內存區(qū)域的唯一目的就是存放對象實例澜掩,幾乎所有的對象實例都在這里分配內存。

Java堆是垃圾收集器管理的主要區(qū)域杖挣,因此很多時候也被稱做“GC堆”肩榕。如果從內存回收的角度看,由于現(xiàn)在收集器基本都是采用的分代收集算法惩妇,所以Java堆中還可以細分為:新生代和老年代株汉;再細致一點的有Eden空間、From Survivor空間歌殃、To Survivor空間等乔妈。

根據(jù)Java虛擬機規(guī)范的規(guī)定,Java堆可以處于物理上不連續(xù)的內存空間中氓皱,只要邏輯上是連續(xù)的即可路召,就像我們的磁盤空間一樣。在實現(xiàn)時波材,既可以實現(xiàn)成固定大小的股淡,也可以是可擴展的,不過當前主流的虛擬機都是按照可擴展來實現(xiàn)的(通過-Xmx和-Xms控制)廷区。

如果在堆中沒有內存完成實例分配唯灵,并且堆也無法再擴展時,將會拋出OutOfMemoryError異常隙轻。

(2) 方法區(qū)(Method Area)

方法區(qū)(Method Area)與Java堆一樣早敬,是各個線程共享的內存區(qū)域,它用于存儲已被虛擬機加載的類信息大脉、常量搞监、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)镰矿。雖然Java虛擬機規(guī)范把方法區(qū)描述為堆的一個邏輯部分琐驴,但是它卻有一個別名叫做Non-Heap(非堆),目的應該是與Java堆區(qū)分開來。

對于習慣在HotSpot虛擬機上開發(fā)和部署程序的開發(fā)者來說绝淡,很多人愿意把方法區(qū)稱為“永久代”(Permanent Generation)宙刘,本質上兩者并不等價,僅僅是因為HotSpot虛擬機的設計團隊選擇把GC分代收集擴展至方法區(qū)牢酵,或者說使用永久代來實現(xiàn)方法區(qū)而已悬包。

Java虛擬機規(guī)范對這個區(qū)域的限制非常寬松,除了和Java堆一樣不需要連續(xù)的內存和可以選擇固定大小或者可擴展外馍乙,還可以選擇不實現(xiàn)垃圾收集布近。相對而言,垃圾收集行為在這個區(qū)域是比較少出現(xiàn)的丝格,但并非數(shù)據(jù)進入了方法區(qū)就如永久代的名字一樣“永久”存在了撑瞧。這個區(qū)域的內存回收目標主要是針對常量池的回收和對類型的卸載,一般來說這個區(qū)域的回收“成績”比較難以令人滿意显蝌,尤其是類型的卸載预伺,條件相當苛刻,但是這部分區(qū)域的回收確實是有必要的曼尊。

根據(jù)Java虛擬機規(guī)范的規(guī)定酬诀,當方法區(qū)無法滿足內存分配需求時,將拋出OutOfMemoryError異常骆撇。

(3) 程序計數(shù)器(Program Counter Register)

程序計數(shù)器(Program Counter Register)是一塊較小的內存空間料滥,它的作用可以看做是當前線程所執(zhí)行的字節(jié)碼的行號指示器。在虛擬機的概念模型里(僅是概念模型艾船,各種虛擬機可能會通過一些更高效的方式去實現(xiàn))葵腹,字節(jié)碼解釋器工作時就是通過改變這個計數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令,分支屿岂、循環(huán)践宴、跳轉、異常處理爷怀、線程恢復等基礎功能都需要依賴這個計數(shù)器來完成阻肩。

由于Java虛擬機的多線程是通過線程輪流切換并分配處理器執(zhí)行時間的方式來實現(xiàn)的,在任何一個確定的時刻运授,一個處理器(對于多核處理器來說是一個內核)只會執(zhí)行一條線程中的指令烤惊。因此,為了線程切換后能恢復到正確的執(zhí)行位置吁朦,每條線程都需要有一個獨立的程序計數(shù)器柒室,各條線程之間的計數(shù)器互不影響,獨立存儲逗宜,我們稱這類內存區(qū)域為“線程私有”的內存雄右。

如果線程正在執(zhí)行的是一個Java方法空骚,這個計數(shù)器記錄的是正在執(zhí)行的虛擬機字節(jié)碼指令的地址;如果正在執(zhí)行的是Natvie方法擂仍,這個計數(shù)器值則為空(Undefined)囤屹。

此內存區(qū)域是唯一一個在Java虛擬機規(guī)范中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域。

(4) JVM棧(JVM Stacks)

與程序計數(shù)器一樣逢渔,Java虛擬機棧(Java Virtual Machine Stacks)也是線程私有的肋坚,它的生命周期與線程相同。虛擬機棧描述的是Java方法執(zhí)行的內存模型:每個方法被執(zhí)行的時候都會同時創(chuàng)建一個棧幀(Stack Frame)用于存儲局部變量表肃廓、操作棧智厌、動態(tài)鏈接、方法出口等信息亿昏。每一個方法被調用直至執(zhí)行完成的過程,就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程档礁。

局部變量表存放了編譯期可知的各種基本數(shù)據(jù)類型(boolean角钩、byte、char呻澜、short递礼、int、float羹幸、long脊髓、double)、對象引用(reference類型栅受,它不等同于對象本身将硝,根據(jù)不同的虛擬機實現(xiàn),它可能是一個指向對象起始地址的引用指針屏镊,也可能指向一個代表對象的句柄或者其他與此對象相關的位置)和returnAddress類型(指向了一條字節(jié)碼指令的地址)依疼。

其中64位長度的long和double類型的數(shù)據(jù)會占用2個局部變量空間(Slot),其余的數(shù)據(jù)類型只占用1個而芥。局部變量表所需的內存空間在編譯期間完成分配律罢,當進入一個方法時,這個方法需要在幀中分配多大的局部變量空間是完全確定的棍丐,在方法運行期間不會改變局部變量表的大小误辑。

在Java虛擬機規(guī)范中,對這個區(qū)域規(guī)定了兩種異常狀況:如果線程請求的棧深度大于虛擬機所允許的深度歌逢,將拋出StackOverflowError異常巾钉;如果虛擬機棧可以動態(tài)擴展(當前大部分的Java虛擬機都可動態(tài)擴展秘案,只不過Java虛擬機規(guī)范中也允許固定長度的虛擬機棧)睛琳,當擴展時無法申請到足夠的內存時會拋出OutOfMemoryError異常盒蟆。

(5) 本地方法棧(Native Method Stacks)

本地方法棧(Native Method Stacks)與虛擬機棧所發(fā)揮的作用是非常相似的,其區(qū)別不過是虛擬機棧為虛擬機執(zhí)行Java方法(也就是字節(jié)碼)服務师骗,而本地方法棧則是為虛擬機使用到的Native方法服務历等。虛擬機規(guī)范中對本地方法棧中的方法使用的語言、使用方式與數(shù)據(jù)結構并沒有強制規(guī)定辟癌,因此具體的虛擬機可以自由實現(xiàn)它寒屯。甚至有的虛擬機(譬如Sun HotSpot虛擬機)直接就把本地方法棧和虛擬機棧合二為一。與虛擬機棧一樣黍少,本地方法棧區(qū)域也會拋出StackOverflowErrorOutOfMemoryError異常寡夹。

3. 參數(shù)配置

(1) trace跟蹤參數(shù)

參數(shù) 作用
-XX:+PrintGC/-verbose:gc 打印GC的簡要信息
-XX:+PrintGCDetails 打印GC的詳細信息
-XX:+PrintGCDateStamps 打印GC發(fā)生的時間
-Xloggc:log/gc.log 指定GC的log位置,以文件輸出
-XX:+PrintHeapAtGC 每一次GC后都打印堆信息
-XX:+HeapDumpOnOutOfMemoryError 當JVM發(fā)生OOM時厂置,自動生成DUMP文件
-XX:HeapDumpPath=${目錄} 生成的DUMP文件的存放位置

(2) 堆參數(shù)配置

參數(shù) 作用
-Xms 初始堆大小菩掏,默認是物理內存的1/64
-Xmx 最大堆大小 默認是物理內存的1/4
-Xmn 年輕代的大小,默認整個堆的3/8
-XX:NewSize 設置新生代最小空間大小
-XX:MaxNewSize 設置新生代最大空間大小
-XX:PermSize 設置永久代最小空間大
-XX:MaxPermSize 設置永久代最大空間大小
-Xss 設置每個線程的堆棧大小
-XX:NewRatio=n 設置年老代和年輕帶的比值昵济,如3智绸,年輕代占整個年輕代年老代和的1/4
-XX:SurvivorRatio=n 年輕代中Eden區(qū)與兩個Survivor區(qū)的比值,注意Survivor區(qū)有兩個访忿,如:3瞧栗,表示Eden:Survivor=3:2,一個Survivor區(qū)占整個年輕代的1/5
-XX:MetaspaceSize 初始空間大小海铆,達到該值就會觸發(fā)垃圾收集進行類型卸載迹恐,同時GC會對該值進行調整:如果釋放了大量的空間,就適當降低該值卧斟;如果釋放了很少的空間殴边,那么在不超過MaxMetaspaceSize時,適當提高該值
-XX:MaxMetaspaceSize 空間最大內存珍语,默認是沒有限制的

老年代空間大姓叶肌:
沒有直接設置老年代的參數(shù),但是可以設置堆空間大小和新生代空間大小兩個參數(shù)來間接控制廊酣,老年代空間大小=堆空間大小-年輕代大空間大小

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末能耻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子亡驰,更是在濱河造成了極大的恐慌晓猛,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凡辱,死亡現(xiàn)場離奇詭異戒职,居然都是意外死亡,警方通過查閱死者的電腦和手機透乾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門洪燥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來磕秤,“玉大人,你說我怎么就攤上這事捧韵∈信兀” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵再来,是天一觀的道長蒙兰。 經常有香客問我,道長芒篷,這世上最難降的妖魔是什么搜变? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮针炉,結果婚禮上挠他,老公的妹妹穿的比我還像新娘。我一直安慰自己篡帕,他們只是感情好殖侵,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著赂苗,像睡著了一般愉耙。 火紅的嫁衣襯著肌膚如雪贮尉。 梳的紋絲不亂的頭發(fā)上拌滋,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天,我揣著相機與錄音猜谚,去河邊找鬼败砂。 笑死,一個胖子當著我的面吹牛魏铅,可吹牛的內容都是我干的昌犹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼览芳,長吁一口氣:“原來是場噩夢啊……” “哼斜姥!你這毒婦竟也來了?” 一聲冷哼從身側響起沧竟,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤铸敏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后悟泵,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杈笔,經...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年糕非,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒙具。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片球榆。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖禁筏,靈堂內的尸體忽然破棺而出持钉,到底是詐尸還是另有隱情,我是刑警寧澤融师,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布右钾,位于F島的核電站,受9級特大地震影響旱爆,放射性物質發(fā)生泄漏舀射。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一怀伦、第九天 我趴在偏房一處隱蔽的房頂上張望脆烟。 院中可真熱鬧,春花似錦房待、人聲如沸邢羔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拜鹤。三九已至,卻和暖如春流椒,著一層夾襖步出監(jiān)牢的瞬間敏簿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工宣虾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留惯裕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓绣硝,卻偏偏與公主長得像蜻势,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鹉胖,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355