JVM淺談

前言

由于先前也遇到過一些性能問題褐墅,OOM算是其中的一大類了樱调。因此也對jvm產(chǎn)生了一些興趣。自己對jvm略做了些研究洽故。后續(xù)繼續(xù)補(bǔ)充贝攒。

從oom引申出去

既然說到oom,首先需要知道oom的原因是什么时甚。為啥會oom嘞隘弊?
oom的定義是outofmemory。當(dāng)內(nèi)存想為對象分配內(nèi)存的時候荒适,發(fā)現(xiàn)內(nèi)存不足以去分配內(nèi)存梨熙,或者gc的時候發(fā)現(xiàn)沒有可以被回收的對象或回收后的內(nèi)存也不足以為對象分配內(nèi)存。
因此拋出這個java異常刀诬。

oom
可以分為以下四類

1.堆溢出:java堆

2.棧溢出:虛擬機(jī)棧和本地方法棧

3.方法區(qū)內(nèi)存溢出:方法區(qū)和內(nèi)存時常量池

4.本機(jī)直接內(nèi)存溢出

因此咽扇,需要先了解堆,棧陕壹,方法區(qū)都是些啥

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

先上圖


file

程序計(jì)數(shù)器:當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器质欲。

java虛擬機(jī)的多線程是通過輪流切換線程,并為線程分配執(zhí)行時間片去運(yùn)行來執(zhí)行的糠馆。每個線程都有一個自己的程序計(jì)數(shù)器嘶伟。我覺得這個可以這么理解:當(dāng)一個線程在運(yùn)行的時候,每執(zhí)行一步程序計(jì)數(shù)器都會有個記錄又碌,記錄當(dāng)前執(zhí)行到哪一步了九昧。如果線程被切換后又切換回來绊袋,那么通過程序計(jì)數(shù)器就能知道執(zhí)行到哪一步了,然后繼續(xù)向下執(zhí)行铸鹰。

虛擬機(jī)棧:每個線程都會有一個虛擬機(jī)棧癌别。虛擬機(jī)棧描述的是java方法執(zhí)行的內(nèi)存模型。因?yàn)榫€程執(zhí)行的過程就是執(zhí)行線程里的一個個方法掉奄,而每個方法都會創(chuàng)建對應(yīng)自己的棧幀规个。

棧幀里存的內(nèi)容如下:

  • 局部變量表:存放了各種編譯期可知基本數(shù)據(jù)類型凤薛,對象引用(引用指針或句柄)

  • 操作數(shù)棧:大多數(shù)指令都要從這里彈出數(shù)據(jù)姓建,執(zhí)行運(yùn)算,然后把結(jié)果壓回操作數(shù)棧

  • 動態(tài)鏈接

  • 方法出口

    64位的long和都double類型數(shù)據(jù)占用2個局部變量空間缤苫,其他數(shù)據(jù)類型占用一個速兔,也就是每個局部變量空間為32位。

    在這個地方活玲,如果線程請求的深度大于虛擬機(jī)允許的深度涣狗,會拋出StackOverflowError.因?yàn)閖vm分配給虛擬機(jī)棧的內(nèi)存是有限的,而每個方法都會有對應(yīng)的棧幀壓入到棧中舒憾,如果調(diào)用方法過多镀钓,那么棧滿了自然也就溢出了。(可能的場景:死循環(huán)代碼镀迂,大量遞歸調(diào)用丁溅,那排查問題的時候也可以由此有一個思路)√阶瘢可以通過調(diào)整-Xss去調(diào)整棧大小窟赏。

大部分java虛擬機(jī)允許動態(tài)擴(kuò)展,但如果擴(kuò)展的時候也申請不到足夠內(nèi)存時箱季,就會報(bào)OOM了涯穷。

本地方法棧:和虛擬機(jī)發(fā)揮作用相似。區(qū)別:虛擬機(jī)棧為虛擬機(jī)執(zhí)行java方法服務(wù)藏雏,本地方法棧為虛擬機(jī)使用的Native方法服務(wù)拷况。Native Method就是一個java調(diào)用非java代碼的接口,Native方法的實(shí)現(xiàn)由非java語言實(shí)現(xiàn)掘殴。讀者不用糾結(jié)蝠嘉,略作了解即可。

:堆是所有線程共享的一塊內(nèi)存杯巨,作用是存放對象實(shí)例蚤告。堆可以分為新生代和老年代。新生代里還可細(xì)分為Eden,From survivor,To survivor等空間服爷。后面講述GC過程時會說到杜恰。

方法區(qū):也是所有線程共享的一塊內(nèi)存获诈,存放被虛擬機(jī)加載的類信息,常量心褐,靜態(tài)變量舔涎,編譯器編譯后的代碼。也就是常說的永久代逗爹。

永久代的大小可以用-XX:MaxPermSize去設(shè)置亡嫌。

運(yùn)行時常量池:方法區(qū)的一部分。存放編譯期生成的各種字面量和符號引用掘而。字面量就是指這個量本身挟冠。比如字面量2,就是指2.

運(yùn)行時常量池有一個重要特性就是動態(tài)性袍睡。常量不一定只有編譯期才能產(chǎn)生知染,運(yùn)行期間也可能將新的常量放入常量池。詳情可見String類的

intern()方法斑胜。

此處推薦這篇博客控淡,對intern()方法介紹的挺清楚的。

https://blog.csdn.net/soonfly/article/details/70147205

直接內(nèi)存:它不是虛擬機(jī)運(yùn)行時數(shù)據(jù)區(qū)的一部分止潘,但也頻繁的被使用掺炭。直接內(nèi)存不會受到j(luò)ava堆大小的限制,但是會受到本機(jī)總內(nèi)存的限制凭戴。

GC過程

GC分為新生代GC(minor gc)和老年代GC(full gc)涧狮。新生代GC的頻率遠(yuǎn)遠(yuǎn)高于老年代。而且

新生代GC的速度會比老年代的GC速度快10倍以上簇宽。根源在于新生代和老年代使用的GC算法不同勋篓。讀者們可以去仔細(xì)思考下(答案文中有,哈哈)魏割。新生代/老年代大小默認(rèn)為1:2譬嚣。

新生代GC過程

新生代里可細(xì)分為Eden,From survivor,To survivor等空間。當(dāng)我們需要給對象分配內(nèi)存的時候钞它,首先我們會在Eden區(qū)為對象分配內(nèi)存拜银,當(dāng)Eden區(qū)內(nèi)存不足時,會發(fā)生minor gc遭垛,此時會把仍然存活的對象放到From survivor尼桶,并給對象標(biāo)記存活次數(shù)1;然后當(dāng)Eden區(qū)再次被用完后锯仪,對Eden區(qū)和From survivor區(qū)篩選出存活的對象泵督,放到To survivor區(qū),清空Eden區(qū)和From survivor區(qū)庶喜,存活次數(shù)加1小腊,之前存活的就是2了救鲤。

以此類推,默認(rèn)是當(dāng)存活次數(shù)到達(dá)15次(可配置)的時候秩冈,把這個對象存入老年代中本缠。同時也可以看到,F(xiàn)rom survivor,To survivor區(qū)始終有一個是空置的入问。所以新生代使用的只有9/10的空間丹锹。
然而大家可以思考一下。Eden區(qū)和survivor區(qū)的大小為8:1芬失,那么發(fā)生minor gc后如果存活的對象
的大小比survivor區(qū)還要大楣黍。這個時候會怎么處理?

這里需要引入一個叫“內(nèi)存分配擔(dān)保機(jī)制”的概念麸折。就是當(dāng)存活的對象連survivor區(qū)都放不下的時候锡凝,這部分放不下的對象會直接進(jìn)入老年代粘昨。老年代是擔(dān)保人垢啼。老年代進(jìn)行擔(dān)保,前提是老年代還有剩余空間张肾。但是每次存活下來的對象大小是不確定的芭析。所以只好取之前每次存儲到老年代的對象大小的平均值。如果大于平均值吞瞪,那么直接full gc馁启。但是為了避免頻繁full gc,仍然會開啟handlepromotionfailure配置芍秆。如下圖

file

老年代GC過程

老年代采用了標(biāo)記整理惯疙,標(biāo)記清楚的算法。老年代會把仍然存活的對象都整理統(tǒng)一放到一邊妖啥。整理完成后就會清楚掉邊界外的對象霉颠。這樣就避免了產(chǎn)生大量的內(nèi)存碎片的問題。但是整理算法相較于新生代采用的復(fù)制算法荆虱,復(fù)雜程度肯定更高蒿偎。這也導(dǎo)致了full gc的速度要遠(yuǎn)遠(yuǎn)慢于minor gc。

本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布怀读!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诉位,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子菜枷,更是在濱河造成了極大的恐慌苍糠,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啤誊,死亡現(xiàn)場離奇詭異岳瞭,居然都是意外死亡歹袁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進(jìn)店門寝优,熙熙樓的掌柜王于貴愁眉苦臉地迎上來条舔,“玉大人,你說我怎么就攤上這事乏矾∶峡梗” “怎么了?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵钻心,是天一觀的道長凄硼。 經(jīng)常有香客問我,道長捷沸,這世上最難降的妖魔是什么摊沉? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮痒给,結(jié)果婚禮上说墨,老公的妹妹穿的比我還像新娘。我一直安慰自己苍柏,他們只是感情好尼斧,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著试吁,像睡著了一般棺棵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上熄捍,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天烛恤,我揣著相機(jī)與錄音,去河邊找鬼余耽。 笑死缚柏,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宾添。 我是一名探鬼主播船惨,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼缕陕!你這毒婦竟也來了粱锐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤扛邑,失蹤者是張志新(化名)和其女友劉穎怜浅,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恶座,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年搀暑,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跨琳。...
    茶點(diǎn)故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡自点,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出脉让,到底是詐尸還是另有隱情桂敛,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布溅潜,位于F島的核電站术唬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏滚澜。R本人自食惡果不足惜粗仓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望设捐。 院中可真熱鬧借浊,春花似錦、人聲如沸挡育。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽即寒。三九已至,卻和暖如春召噩,著一層夾襖步出監(jiān)牢的瞬間母赵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工具滴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凹嘲,地道東北人。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓构韵,卻偏偏與公主長得像周蹭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子疲恢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評論 2 361

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

  • 前言 由于先前也遇到過一些性能問題凶朗,OOM算是其中的一大類了。因此也對jvm產(chǎn)生了一些興趣显拳。自己對jvm略做了...
    betterFighter閱讀 313評論 0 1
  • JVM架構(gòu) 當(dāng)一個程序啟動之前棚愤,它的class會被類裝載器裝入方法區(qū)(Permanent區(qū)),執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,673評論 0 7
  • http://www.cnblogs.com/angeldevil/p/3801189.html值得一看 Clas...
    snail_knight閱讀 1,428評論 1 0
  • 作者:一字馬胡 轉(zhuǎn)載標(biāo)志 【2017-11-12】 更新日志 日期更新內(nèi)容備注 2017-11-12新建文章初版 ...
    beneke閱讀 2,211評論 0 7
  • 一 、java虛擬機(jī)底層結(jié)構(gòu)詳解 我們知道宛畦,一個JVM實(shí)例的行為不光是它自己的事瘸洛,還涉及到它的子系統(tǒng)、存儲區(qū)域次和、...
    葡萄喃喃囈語閱讀 1,490評論 0 4