JVM

圖1

方法區(qū)(Method Area)與Java堆一樣,是各個(gè)線程共享的內(nèi)存區(qū)域,它用于存儲(chǔ)已被虛擬機(jī)加載的類信息促煮、常量、靜態(tài)變量供置、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)韩玩。雖然Java虛擬機(jī)規(guī)范把方法區(qū)描述為堆的一個(gè)邏輯部分人灼,但是它卻有一個(gè)別名叫做Non-Heap(非堆),目的應(yīng)該是與Java堆區(qū)分開來绳匀。

程序計(jì)數(shù)器(Program Counter Register)是一塊較小的內(nèi)存空間,它可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。在虛擬機(jī)的概念模型里(僅是概念模型疾棵,各種虛擬機(jī)可能會(huì)通過一些更高效的方式去實(shí)現(xiàn))盗飒,字節(jié)碼解釋器工作時(shí)就是通過改變這個(gè)計(jì)數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令,分支陋桂、循環(huán)逆趣、跳轉(zhuǎn)、異常處理嗜历、線程恢復(fù)等基礎(chǔ)功能都需要依賴這個(gè)計(jì)數(shù)器來完成宣渗。

Java虛擬機(jī)棧(Java Virtual Machine Stacks)也是線程私有的,它的生命周期與線程相同梨州。虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個(gè)方法在執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)棧幀(Stack Frame )用于存儲(chǔ)局部變量表痕囱、操作數(shù)棧、動(dòng)態(tài)鏈接暴匠、方法出口等信息鞍恢。每一個(gè)方法從調(diào)用直至執(zhí)行完成的過程,就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中入棧到出棧的過程每窖。(局部變量表:局部變量表存放了編譯期可知的各種基本數(shù)據(jù)類型(boolean帮掉、byte、char窒典、short蟆炊、int、float瀑志、long涩搓、double)、對(duì)象引用(reference類型劈猪,它不等同于對(duì)象本身昧甘,可能是一個(gè)指向?qū)ο笃鹗嫉刂返囊弥羔槪部赡苁侵赶蛞粋€(gè)代表對(duì)象的句柄或其他與此對(duì)象相關(guān)的位置)和returnAddress類型(指向了一條字節(jié)碼指令的地址)战得。)

本地方法棧(Native Method Stack)與虛擬機(jī)棧所發(fā)揮的作用是非常相似的充边,它們之間的區(qū)別不過是虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則為虛擬機(jī)使用到的Native方法服務(wù)贡避。在虛擬機(jī)規(guī)范中對(duì)本地方法棧中方法使用的語言痛黎、使用方式與數(shù)據(jù)結(jié)構(gòu)并沒有強(qiáng)制規(guī)定,因此具體的虛擬機(jī)可以自由實(shí)現(xiàn)它刮吧。甚至有的虛擬機(jī)(譬如Sun HotSpot虛擬機(jī))直接就把本地方法棧和虛擬機(jī)棧合二為一湖饱。與虛擬機(jī)棧一樣,本地方法棧區(qū)域也會(huì)拋出StackOverflowError和OutOfMemoryError異常杀捻。(native method含義: 一個(gè)Native Method就是一個(gè)java調(diào)用非java代碼的接口井厌。一個(gè)Native Method是這樣一個(gè)java的方法:該方法的實(shí)現(xiàn)由非java語言實(shí)現(xiàn),比如C。這個(gè)特征并非java所特有仅仆,很多其它的編程語言都有這一機(jī)制器赞,比如在C++中,你可以用extern "C"告知C++編譯器去調(diào)用一個(gè)C的函數(shù)墓拜。)

Java堆(Java Heap)是Java虛擬機(jī)所管理的內(nèi)存中最大的一塊港柜。Java堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建咳榜。此內(nèi)存區(qū)域的唯一目的就是存放對(duì)象實(shí)例夏醉,幾乎所有的對(duì)象實(shí)例都在
這里分配內(nèi)存。

2.垃圾收集算法
1.標(biāo)記-清除算法
最基礎(chǔ)的收集算法是“標(biāo)記-清除”(Mark-Sweep)算法涌韩,如同它的名字一樣畔柔,算法分為“標(biāo)記”和“清
除”兩個(gè)階段:首先標(biāo)記出所有需要回收的對(duì)象臣樱,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象靶擦,它的標(biāo)記過程其實(shí)在前一節(jié)講述對(duì)象標(biāo)記判定時(shí)已經(jīng)介紹過了雇毫。之所以說它是最基礎(chǔ)的收集算法,是因?yàn)楹罄m(xù)的收集算法都是基于這種思路并對(duì)其不足進(jìn)行改進(jìn)而得到的嘴拢。它的主要不足有兩個(gè):一個(gè)是效率問題桩盲,標(biāo)記和清除兩個(gè)過程的效率都不高;另一個(gè)是空間問題,標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片捞蛋,空間碎片太多可能會(huì)導(dǎo)致以后在程序運(yùn)行過程中需要分配較大對(duì)象時(shí),無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作拟杉。標(biāo)記—清除算法的執(zhí)行過程如圖

圖2

2.復(fù)制算法
為了解決效率問題庄涡,一種稱為“復(fù)制”(Copying)的收集算法出現(xiàn)了,它將可用內(nèi)存按容量劃分為大小相等的兩塊搬设,每次只使用其中的一塊。當(dāng)這一塊的內(nèi)存用完了拿穴,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已使用過的內(nèi)存空間一次清理掉默色。這樣使得每次都是對(duì)整個(gè)半?yún)^(qū)進(jìn)行內(nèi)存回收,內(nèi)存分配時(shí)也就不用考慮內(nèi)存碎片等復(fù)雜情況呕诉,只要移動(dòng)堆頂指針,按順序分配內(nèi)存即可甩挫,實(shí)現(xiàn)簡(jiǎn)單,運(yùn)行高效伊者。只是這種算法的代價(jià)是將內(nèi)存縮小為了原來的一半,未免太高了一點(diǎn)删壮。復(fù)制算法的執(zhí)行過程如圖

圖3

3.標(biāo)記-整理算法
復(fù)制收集算法在對(duì)象存活率較高時(shí)就要進(jìn)行較多的復(fù)制操作,效率將會(huì)變低税灌。更關(guān)鍵的是亿虽,如果不想浪費(fèi)50%的空間,就需要有額外的空間進(jìn)行分配擔(dān)保洛勉,以應(yīng)對(duì)被使用的內(nèi)存中所有對(duì)象都100%存活的極端情況,所以在老年代一般不能直接選用這種算法攻走。根據(jù)老年代的特點(diǎn)此再,有人提出了另外一種“標(biāo)記-整理”(Mark-Compact)算法,標(biāo)記過程仍然與“標(biāo)記-清除”算法一樣输拇,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活的對(duì)象都向一端移動(dòng)逛裤,然后直接清理掉端邊界以外的內(nèi)存猴抹,“標(biāo)記-整理”算法的示意圖如圖

圖4

4.分代收集算法
當(dāng)前商業(yè)虛擬機(jī)的垃圾收集都采用“分代收集”(Generational Collection)算法,這種算法并沒有什么新
的思想洽糟,只是根據(jù)對(duì)象存活周期的不同將內(nèi)存劃分為幾塊炉菲。一般是把Java堆分為新生代和老年代,這樣就可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ㄖ龆T谛律徐艚龋看卫占瘯r(shí)都發(fā)現(xiàn)有大批對(duì)象死去,只有少量存活道偷,那就選用復(fù)制算法,只需要付出少量存活對(duì)象的復(fù)制成本就可以完成收集并巍。而老年代中因?yàn)閷?duì)象存活率高换途、沒有額外空間對(duì)它進(jìn)行分配擔(dān)保,就必須使用“標(biāo)記—清理”或者“標(biāo)記—整理”算法來進(jìn)行回收军拟。

Java堆用于存儲(chǔ)對(duì)象實(shí)例,只要不斷地創(chuàng)建對(duì)象肾档,并且保證GC Roots到對(duì)象之間有可達(dá)路徑來避免垃圾回收機(jī)制清除這些對(duì)象辫继,那么在對(duì)象數(shù)量到達(dá)最大堆的容量限制后就會(huì)產(chǎn)生內(nèi)存溢出異常。
public class HeapTest {
static class OOMObject {
}

public static void main(String[] args) {
    List<OOMObject> list = new ArrayList<OOMObject>();
    while (true) {
        list.add( new OOMObject());
    }
}

}
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.util.Arrays.copyOf(Unknown Source)
at java.util.ArrayList.ensureCapacity(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at org.myorg.algorithm.HeapTest.main( HeapTest.java:13)

Permgen Space:permenant genaration space 永久代區(qū)域

判斷對(duì)象是否存活的算法是這樣的:給對(duì)象中添加一個(gè)引用計(jì)數(shù)器速种,每當(dāng)有一個(gè)地方引用它時(shí)低千,計(jì)數(shù)器值就加1馏颂;當(dāng)引用失效時(shí),計(jì)數(shù)器值就減1救拉;任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末告喊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子黔姜,更是在濱河造成了極大的恐慌,老刑警劉巖淮椰,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纳寂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡忽媒,警方通過查閱死者的電腦和手機(jī)腋粥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來灯抛,“玉大人金赦,你說我怎么就攤上這事对嚼。” “怎么了漠烧?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵靡砌,是天一觀的道長。 經(jīng)常有香客問我度液,道長画舌,這世上最難降的妖魔是什么堕担? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任曲聂,我火速辦了婚禮,結(jié)果婚禮上朋腋,老公的妹妹穿的比我還像新娘膜楷。我一直安慰自己贞奋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布察蹲。 她就那樣靜靜地躺著催训,像睡著了一般。 火紅的嫁衣襯著肌膚如雪漫拭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天审胚,我揣著相機(jī)與錄音礼旅,去河邊找鬼。 笑死痘系,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的龄坪。 我是一名探鬼主播复唤,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼妓局!你這毒婦竟也來了呈宇?” 一聲冷哼從身側(cè)響起跟磨,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎哎榴,沒想到半個(gè)月后僵蛛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體迎变,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年衣形,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倒源。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡句狼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出腻菇,到底是詐尸還是另有隱情,我是刑警寧澤糖耸,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布丘薛,位于F島的核電站,受9級(jí)特大地震影響榔袋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜妥粟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一吏够、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锅知,春花似錦、人聲如沸桩警。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烂叔。三九已至,卻和暖如春蒜鸡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逢防。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來泰國打工胞四, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恬汁,地道東北人辜伟。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓导狡,卻偏偏與公主長得像约巷,于是被迫代替她去往敵國和親旱捧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • JVM內(nèi)存模型Java虛擬機(jī)(Java Virtual Machine=JVM)的內(nèi)存空間分為五個(gè)部分氓癌,分別是: ...
    光劍書架上的書閱讀 2,483評(píng)論 2 26
  • 這篇文章是我之前翻閱了不少的書籍以及從網(wǎng)絡(luò)上收集的一些資料的整理贪婉,因此不免有一些不準(zhǔn)確的地方,同時(shí)不同JDK版本的...
    高廣超閱讀 15,545評(píng)論 3 83
  • 原文閱讀 前言 這段時(shí)間懈怠了疲迂,罪過莫湘! 最近看到有同事也開始用上了微信公眾號(hào)寫博客了,挺好的~給他們點(diǎn)贊幅垮,這博客我...
    碼農(nóng)戲碼閱讀 5,948評(píng)論 2 31
  • 1.一些概念 1.1.數(shù)據(jù)類型 Java虛擬機(jī)中,數(shù)據(jù)類型可以分為兩類:基本類型和引用類型巩螃。基本類型的變量保存原始...
    落落落落大大方方閱讀 4,520評(píng)論 4 86
  • 在心靈的荒原上 我點(diǎn)燃了一個(gè)人的篝火 就像在星空之下?lián)u晃的醉漢 你離開了我 嫁到了另一個(gè)村莊 你說你并不愿意 但每...
    楊孜閱讀 966評(píng)論 0 2