JVM-java內(nèi)存區(qū)域與內(nèi)存溢出異常

JVM-java內(nèi)存區(qū)域與內(nèi)存溢出異常

1 說明

java 與 c++之間有一堵由內(nèi)存動態(tài)分配和垃圾回收技術(shù)所圍成的高墻呻率,墻外的人想進(jìn)來躏将, 墻內(nèi)的人想出去锄弱。然而java的使用者就是這些墻里的人。這篇文章就是介紹java虛擬機(jī)內(nèi)存的各個區(qū)域祸憋,講述這些區(qū)域的作用会宪,服務(wù)對象以及其中可能產(chǎn)生的問題。從這里蚯窥,我們開始進(jìn)行翻墻工作掸鹅。然而請注意,墻的那邊是高能區(qū)......

2 運(yùn)行時數(shù)據(jù)區(qū)域

java虛擬機(jī)在執(zhí)行java程序過程中拦赠,會把它管理的內(nèi)存分成若干個不同的數(shù)據(jù)區(qū)巍沙。有的區(qū)域鎖著虛擬機(jī)進(jìn)程的啟動而存在,有些是依賴用戶進(jìn)程建立與銷毀荷鼠。在java7 的虛擬機(jī)規(guī)范中規(guī)定句携,虛擬機(jī)所管理的內(nèi)存將會包括如下幾個運(yùn)行時數(shù)據(jù)區(qū)域。下面就是java虛擬機(jī)運(yùn)行時數(shù)據(jù)區(qū):


圖片摘自網(wǎng)絡(luò)

2.1 程序計(jì)數(shù)器

程序計(jì)數(shù)器是一塊較小的內(nèi)存空間允乐,在虛擬機(jī)概念模型里矮嫉,程序計(jì)數(shù)器的值是為了給字節(jié)碼解釋器提給選取嚇一跳需要執(zhí)行的字節(jié)碼只能提供幫助的。在分支牍疏,循環(huán)蠢笋,跳轉(zhuǎn),異常處理鳞陨,線程恢復(fù)都需要依賴這個計(jì)數(shù)器昨寞。因?yàn)槌绦蛴?jì)數(shù)器能幫助線程跳轉(zhuǎn)和恢復(fù):java虛擬機(jī)執(zhí)行多線程是采用輪流切換的機(jī)制,因此為了在切換回來的時候知道在哪里繼續(xù)執(zhí)行,所以才用程序計(jì)數(shù)器编矾。

由此可知熟史,程序計(jì)數(shù)器是線程私有的內(nèi)存區(qū)>程序技術(shù)器也是唯一一個沒有規(guī)定任何OOM(OutOfMemoryError)情況的區(qū)域馁害。

2.2 java虛擬機(jī)棧

java虛擬機(jī)棧是描述java方法執(zhí)行的內(nèi)存模型窄俏,每個方法執(zhí)行時候都會建立一個“棧幀”用于存儲:局部變量,操作數(shù)棧碘菜,動態(tài)鏈接凹蜈,方法的返回信息等。每一個方法的調(diào)用都是一個棧幀入棧到出棧的過程忍啸。經(jīng)常有人把java內(nèi)存區(qū)域分成“堆”和“椦鎏梗”,然而java的內(nèi)存區(qū)域要遠(yuǎn)遠(yuǎn)復(fù)雜的多计雌,而大家口中的“椙幕危”就是這里的“java虛擬機(jī)棧”或者更小一點(diǎn)凿滤,是虛擬機(jī)棧里的“局部變量表”部分妈橄。局部變量表存儲了編譯期就可以知道的基本數(shù)據(jù)類型,引用對象翁脆,和returnAddress類型眷蚓。局部變量表的內(nèi)存空間在編譯期就已經(jīng)完成分配了。當(dāng)進(jìn)入一個方法時候反番,這個方法余姚在幀中非配多大的局部變量空間是確定的了(大家可以想一下沙热,方法主要是由什么組成的,不就是局部變量么罢缸?既然都已經(jīng)知道要用什么局部變量了篙贸,那么這個內(nèi)存空間豈不是已經(jīng)確定了?)在java虛擬機(jī)規(guī)范中枫疆,對虛擬機(jī)棧規(guī)定了兩種異常情況:

  • StackOverflowError: 如果線程請求的棧深度大于虛擬機(jī)所允許的深度爵川,則拋出棧溢出錯誤。
  • OOM 如果虛擬機(jī)棧的內(nèi)存無法繼續(xù)擴(kuò)展养铸,則拋出內(nèi)存超出錯誤雁芙。

有上可知:java虛擬機(jī)棧也是線程私有

2.3 本地方法棧

本地方法棧與虛擬機(jī)棧發(fā)揮的作用相似,不過虛擬機(jī)棧調(diào)用的是java的方法钞螟,而本地方法棧調(diào)用的是Native方法兔甘。因?yàn)閖ava虛擬機(jī)規(guī)范中并沒有規(guī)定“本地方法棧”要用什么語言實(shí)現(xiàn)鳞滨,所以甚至有些虛擬機(jī)都把“本地方法椂幢海”與“虛擬機(jī)棧”合二為一。與虛擬機(jī)棧一樣澡匪,同樣會拋出上面的兩個異常熔任。

2.4 java堆

java堆是java虛擬機(jī)所管理的內(nèi)存中的最大的一塊。此內(nèi)存的唯一目的就是存放對象實(shí)例唁情!幾乎所有的對象實(shí)例都在這里分配內(nèi)存疑苔。“java堆”是java垃圾回收機(jī)制管理的主要區(qū)域甸鸟,因此也被稱為“GC堆”惦费。在內(nèi)存回收的角度來看,由于算法多采用的是分代回收抢韭,所以又被分為:新生代薪贫,老年代。 在細(xì)致一點(diǎn)的可以分為:Eden區(qū)刻恭, From survivor空間和 To survivor空間瞧省。在內(nèi)存分配的角度來說,java堆可以分成多個線程私有的分配緩沖區(qū)TLAB(Thread Local Allocation Buffer)鳍贾。

java堆 是內(nèi)存共享的

2.5 方法區(qū)

方法區(qū)與java堆一樣鞍匾,用來存儲已經(jīng)被虛擬機(jī)加載的類信息、常量贾漏、靜態(tài)變量候学、及時編譯后的代碼數(shù)據(jù)。(那為什么叫做方法區(qū)呢纵散?很好奇)方法區(qū)很多人有稱之為“永久代”梳码,雖然這么稱呼并不完全準(zhǔn)確。原來的字符串常量池在永久代里伍掀,但是現(xiàn)在看來這么設(shè)計(jì)并不是一個好的作法(因?yàn)镾tring.intern()方法掰茶,可以動態(tài)的向常量池用添加字符串,如果永久代不清理的話/換句話說清理起來很難蜜笤,就會導(dǎo)致內(nèi)存泄露濒蒋。)

也是線程共享的

3 對象的創(chuàng)建

java是一門面向?qū)ο蟮恼Z言。在java程序運(yùn)行過程中把兔,無時無刻不在有對象被創(chuàng)建沪伙。在語言成面上,僅僅是一個new而已县好。但是在虛擬機(jī)中围橡,又是一個怎樣的景象呢?

  • (1) 當(dāng)虛擬機(jī)遇到一條new指令的適合缕贡,首先將去檢查這個指令的參數(shù)是否能在常量池中定位到一個類的符號引用翁授,并且檢查這個符號引用代表的類是否已經(jīng)被加載拣播、解析、初始化過的收擦。如果沒有贮配,那必須先進(jìn)性相應(yīng)的類的初始化。

  • (2) 當(dāng)類加載檢查后塞赂,接下來虛擬機(jī)為新生對象分配內(nèi)存泪勒,對象所需的內(nèi)存大小在類加載后便可以完全確定下來。然后分配對象的任務(wù)就等同于把一塊大小確定的內(nèi)存劃分出來:* 指針碰撞 * 如果內(nèi)存區(qū)域是卻對規(guī)整的减途,所有已經(jīng)分配的內(nèi)存在一起酣藻,沒有分配的內(nèi)存在一起。則就可以在中間設(shè)置一個指針鳍置,當(dāng)創(chuàng)建新的對象時候,就把指針向沒有分配的地方移動即可送淆。

    • Serial税产、ParNew 等帶有Compact過程的收集器,則采用的是指針碰撞偷崩。
    • 空閑列表: 如果內(nèi)存是不規(guī)整的辟拷,則用一張表記錄哪些是分配的,哪些是沒有分配的阐斜。在沒有分配的內(nèi)存中取出一塊比較大的內(nèi)存使用衫冻,并且記錄下情況。
    • 使用CMS這種基于Mark-Sweep算法的收集器時谒出。
  • (3) 上面的情況是在單線程的情況下隅俘,如果在多線程的情況下有如下的解決辦法:一種是對分配內(nèi)存的動作進(jìn)行同步---采用CAS+失敗重試的方式保證操作的原子性。第二種是在每個線程上都分配一塊內(nèi)存笤喳,自己線程的對象为居,在自己的內(nèi)存上進(jìn)行分配(TLAB)。

4 一個有意思的現(xiàn)象

public class RuntimeConstantPoolOOM{ 
    public static void main(String[] args){
        String str1 = new StringBuffer("計(jì)算機(jī)").append("軟件").toString();     
        System.out.println(str1.intern() == str1); String str2 = new  StringBuffer("ja").append("va").toString(); 
        System.out.println(str2.intern() == str2) 
    }
}

上面的這段代碼杀狡,如果在1.6執(zhí)行蒙畴,則都輸出false:因?yàn)镾tringBuffer是在堆中申請的內(nèi)存,String.intern是將對象復(fù)制到方法區(qū)(常量池)中呜象。所以兩個不是指向一個地方膳凝; 如果是在1.7中,則第一個輸出true蹬音, 第二個輸出false楼入, 因?yàn)?.7中的intern方法不再是復(fù)制對象,而是記錄復(fù)制的引用。所以第一個輸出true,而java這里并不是第一次出現(xiàn)衫画,所以常量池中的引用并不是內(nèi)存中的引用,所以輸出false;

內(nèi)容學(xué)習(xí)自GC博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末愿阐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子舒裤,更是在濱河造成了極大的恐慌鲜滩,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件豌汇,死亡現(xiàn)場離奇詭異宛徊,居然都是意外死亡逻澳,警方通過查閱死者的電腦和手機(jī)闸天,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斜做,“玉大人苞氮,你說我怎么就攤上這事≡上恚” “怎么了葱淳?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長抛姑。 經(jīng)常有香客問我,道長艳狐,這世上最難降的妖魔是什么定硝? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮毫目,結(jié)果婚禮上蔬啡,老公的妹妹穿的比我還像新娘。我一直安慰自己镀虐,他們只是感情好箱蟆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著刮便,像睡著了一般空猜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上恨旱,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天辈毯,我揣著相機(jī)與錄音,去河邊找鬼搜贤。 笑死谆沃,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的仪芒。 我是一名探鬼主播唁影,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼耕陷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了据沈?” 一聲冷哼從身側(cè)響起哟沫,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卓舵,沒想到半個月后南用,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掏湾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年裹虫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片融击。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡筑公,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出尊浪,到底是詐尸還是另有隱情匣屡,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布拇涤,位于F島的核電站捣作,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鹅士。R本人自食惡果不足惜券躁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掉盅。 院中可真熱鬧也拜,春花似錦、人聲如沸趾痘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽永票。三九已至卵贱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓦侮,已是汗流浹背艰赞。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肚吏,地道東北人方妖。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像罚攀,于是被迫代替她去往敵國和親党觅。 傳聞我的和親對象是個殘疾皇子雌澄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

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