jvm內(nèi)存分配淺談

一、jvm運(yùn)行時(shí)內(nèi)存區(qū)域劃分:

看圖說(shuō)話轻抱,JVM大致分為五個(gè)區(qū)域:方法區(qū)倘要、堆區(qū)、程序計(jì)數(shù)器、虛擬機(jī)棧和本地方法棧封拧。其中方法區(qū)和堆區(qū)是線程共享志鹃,剩下三者則屬于非線程共享。

1.1泽西、程序計(jì)數(shù)器(線程私有曹铃,生命周期與線程相同)

????????一塊較小的內(nèi)存區(qū)域,用于存儲(chǔ)當(dāng)前線程指令的地址捧杉,通過(guò)改變程序計(jì)數(shù)器的值來(lái)執(zhí)行下一條需要執(zhí)行的指令陕见。因?yàn)橐粋€(gè)處理器同一時(shí)間只能處理一條線程種的指令。所以為了線程恢復(fù)后味抖,線程能從正確的位置開(kāi)始執(zhí)行评甜,必須要每條開(kāi)辟一個(gè)獨(dú)立的程序計(jì)數(shù)器記錄。所以:該內(nèi)存屬于“線程私有”內(nèi)存仔涩。

1.2忍坷、Java虛擬機(jī)棧(線程私有,生命周期與線程相同)

?????????虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個(gè)方法被執(zhí)行的時(shí)候都會(huì)創(chuàng)建一個(gè)棧幀用于存儲(chǔ)局部變量表熔脂,操作棧佩研,動(dòng)態(tài)鏈接,方法出口等信息霞揉。每一個(gè)方法被調(diào)用的過(guò)程就對(duì)應(yīng)一個(gè)棧幀在虛擬機(jī)棧中從入棧到出棧的過(guò)程旬薯。

? ? ? ? 局部變量表存放了編譯器可知的各種基本數(shù)據(jù)類型、對(duì)象引用和returnAddress類型(指向一條字節(jié)碼指令的地址)适秩。局部變量表所需的內(nèi)存空間在編譯器完成分配绊序,當(dāng)進(jìn)入一個(gè)方法時(shí)這個(gè)方法需要在幀中分配多大的內(nèi)存空間是完全確定的,運(yùn)行期間不會(huì)改變局部變量表的大小秽荞。(64為長(zhǎng)度的long和double會(huì)占用兩個(gè)局部變量空間政模,其他的數(shù)據(jù)類型占用一個(gè))

?????Java虛擬機(jī)棧可能出現(xiàn)兩種類型的異常:1. 線程請(qǐng)求的棧深度大于虛擬機(jī)允許的棧深度蚂会,將拋出StackOverflowError淋样。2.虛擬機(jī)棧空間可以動(dòng)態(tài)擴(kuò)展胁住,當(dāng)動(dòng)態(tài)擴(kuò)展是無(wú)法申請(qǐng)到足夠的空間時(shí)趁猴,拋出OutOfMemory異常。

1.3彪见、本地方法棧(線程私有儡司,生命周期與線程相同)

? ? ? ? 發(fā)揮的作用和虛擬機(jī)棧類似,只不過(guò)它是為虛擬機(jī)的Native方法服務(wù)余指。(一個(gè)Native方法就是一個(gè)java調(diào)用非java代碼的接口捕犬。目的是:使用其它語(yǔ)言跷坝,調(diào)用與更底層進(jìn)行直接交互。跳過(guò)中間步驟碉碉,提高程序的執(zhí)行效率)

1.4柴钻、堆區(qū)(線程共享,生命周期與jvm存亡)

????????Java的堆是一個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū),類的對(duì)象從中分配空間垢粮。這些對(duì)象內(nèi)存不需要程序代碼來(lái)顯式的釋放贴届。堆是由垃圾回收來(lái)負(fù)責(zé)的,堆的優(yōu)勢(shì)是可以動(dòng)態(tài)地分配內(nèi)存大小蜡吧,生存期也不必事先告訴編譯器毫蚓,因?yàn)樗窃谶\(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存的。

????????Java堆是垃圾收集器管理的主要區(qū)域昔善,所以也稱為“GC堆”元潘。由于現(xiàn)在的垃圾收集器基本上都是采用分代收集算法,所以Java堆還可細(xì)分為:新生代和老生代君仆。在細(xì)致一點(diǎn)可分為Eden空間翩概,F(xiàn)rom Survivor空間,To Survivor空間袖订。如果從內(nèi)存分配的角度看,線程共享的Java堆可劃分出多個(gè)線程私有的分配緩沖區(qū)嗅虏。

1.5洛姑、方法區(qū)(線程共享,生命周期與jvm存亡)

????????方法區(qū)也是線程共享的區(qū)域皮服,用于存儲(chǔ)已經(jīng)被虛擬機(jī)加載的類信息楞艾,常量,靜態(tài)變量和即時(shí)編譯器(JIT)編譯后的代碼等數(shù)據(jù)龄广。

1.6硫眯、運(yùn)行時(shí)常量池

????????運(yùn)行時(shí)常量池是方法區(qū)的一部分。CLass文件中除了有類的版本择同、字段两入、方法、接口等描述信息外敲才,還有一項(xiàng)信息是常量池裹纳,用于存放編譯期生成的各種字面量和符號(hào)引用,這部分內(nèi)容將在類加載后進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中存放紧武。

????????運(yùn)行時(shí)常量池相對(duì)于CLass文件常量池的另外一個(gè)重要特征是具備動(dòng)態(tài)性剃氧,Java語(yǔ)言并不要求常量一定只有編譯期才能產(chǎn)生,也就是并非預(yù)置入CLass文件中常量池的內(nèi)容才能進(jìn)入方法區(qū)運(yùn)行時(shí)常量池阻星,運(yùn)行期間也可能將新的常量放入池中朋鞍,這種特性被開(kāi)發(fā)人員利用比較多的就是String類的intern()方法。


class文件中常量池的內(nèi)容

二、各個(gè)區(qū)域的內(nèi)存溢出問(wèn)題

????????內(nèi)存溢出理解:當(dāng)程序需要申請(qǐng)內(nèi)存的時(shí)候滥酥,由于沒(méi)有足夠的內(nèi)存更舞,此時(shí)就會(huì)拋出OutOfMemoryError,這就是內(nèi)存溢出恨狈。

????????2.1疏哗、程序計(jì)數(shù)器是jvm唯一一塊區(qū)域不存在內(nèi)存溢出問(wèn)題的。

????????2.2禾怠、虛擬機(jī)棧和本地方法棧內(nèi)存溢出:如果某線程請(qǐng)求的棧幀深度大于虛擬機(jī)允許的最大深度返奉,將拋出StackOverflow異常。

????????2.3吗氏、方法區(qū)內(nèi)存溢出:根據(jù)它存儲(chǔ)的Class相關(guān)信息(類名芽偏、常量池、字段描述弦讽、方法描述)來(lái)看污尉。當(dāng)大量的類占用填滿方法區(qū)時(shí),自然會(huì)拋出OutOfMemoryError異常往产。

????????2.4被碗、堆區(qū)內(nèi)存溢出:當(dāng)對(duì)象實(shí)例大量存在,并超出虛擬機(jī)設(shè)置對(duì)內(nèi)存設(shè)置上限仿村,自然會(huì)拋出OutOfMemoryError異常锐朴。


三、內(nèi)存溢出產(chǎn)生的一個(gè)不可忽視原因——內(nèi)存泄漏

? ? ? ? 3.1蔼囊、內(nèi)存泄漏理解:已經(jīng)申請(qǐng)的內(nèi)存焚志,但無(wú)法被釋放。這一部分內(nèi)存空間就會(huì)一直占用著畏鼓,當(dāng)越來(lái)越多的內(nèi)存泄漏酱酬,隨之而來(lái)的就是內(nèi)存空間不足,拋出OutOfMemoryError異常云矫。

? ? ? ? 3.2膳沽、jvm對(duì)對(duì)象釋放的處理算法:可達(dá)性分析算法。

? ? ? ? ? ? 這個(gè)算法的基本思路就是通過(guò)一系列名為"GC Roots"的對(duì)象作為起始點(diǎn)让禀,從這些節(jié)點(diǎn)開(kāi)始向下搜索贵少,搜索所走過(guò)的路徑稱為引用鏈(Reference Chain),當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連時(shí)堆缘,則證明此對(duì)象是不可用的滔灶,下圖對(duì)象object5, object6, object7雖然有互相判斷,但它們到GC Roots是不可達(dá)的吼肥,所以它們將會(huì)判定為是可回收對(duì)象录平。

GC Root

在Java語(yǔ)言里麻车,可作為GC Roots對(duì)象的包括如下幾種:

??? a.虛擬機(jī)棧的本地變量表中的引用的對(duì)象

??? b.方法區(qū)中的類靜態(tài)屬性引用的對(duì)象

??? c.方法區(qū)中的常量引用的對(duì)象

????d.本地方法棧中JNI的引用的對(duì)象?


四、常見(jiàn)內(nèi)存泄漏場(chǎng)景

? ??4.1斗这、靜態(tài)集合類引起內(nèi)存泄漏:

????????像HashMap动猬、Vector等這些靜態(tài)變量的生命周期和應(yīng)用程序一致,他們所引用的所有的對(duì)象也不能被釋放表箭,因?yàn)樗麄円矊⒁恢北籚ector等引用著赁咙。

? ??4.2、監(jiān)聽(tīng)器

????????在java 編程中免钻,我們都需要和監(jiān)聽(tīng)器打交道彼水,通常一個(gè)應(yīng)用當(dāng)中會(huì)用到很多監(jiān)聽(tīng)器,我們會(huì)調(diào)用一個(gè)控件的諸如addXXXListener()等方法來(lái)增加監(jiān)聽(tīng)器极舔,但往往在釋放對(duì)象的時(shí)候卻沒(méi)有記住去刪除這些監(jiān)聽(tīng)器凤覆,從而增加了內(nèi)存泄漏的機(jī)會(huì)。

? ??4.3拆魏、各種連接

????????比如數(shù)據(jù)庫(kù)連接(dataSourse.getConnection())盯桦,網(wǎng)絡(luò)連接(socket)和io連接,除非其顯式的調(diào)用了其close()方法將其連接關(guān)閉渤刃,否則是不會(huì)自動(dòng)被GC 回收的拥峦。這種情況下一般都會(huì)在try里面去的連接,在finally里面釋放連接卖子。

? ??4.4略号、單例模式

????????不正確使用單例模式是引起內(nèi)存泄漏的一個(gè)常見(jiàn)問(wèn)題,單例對(duì)象在初始化后將在JVM的整個(gè)生命周期中存在(以靜態(tài)變量的方式)揪胃,如果單例對(duì)象持有外部的引用璃哟,那么這個(gè)對(duì)象將不能被JVM正撤兆粒回收喊递,導(dǎo)致內(nèi)存泄漏.



問(wèn)答環(huán)節(jié)。

一阳似、為什么需要了解jvm內(nèi)存分配呢骚勘?平常碼代碼,我只要規(guī)范使用java手冊(cè)撮奏,似乎問(wèn)題照樣能做好需求俏讹。

????????了解內(nèi)存分配主要是為了,當(dāng)出現(xiàn)內(nèi)存泄漏和內(nèi)存溢出時(shí)畜吊,javaer能更好的排查錯(cuò)誤泽疆。也是為了能更好的提升java的性能,對(duì)其調(diào)優(yōu)玲献。規(guī)范是別人總結(jié)的經(jīng)驗(yàn)殉疼,遵守它梯浪,能盡可能避免異常問(wèn)題;好奇它瓢娜,了解它挂洛,我們更是能在出現(xiàn)問(wèn)題時(shí),自己解決它眠砾。豈不美滋虏劲。


????我是先生,找尋著那位迷路的Miss褒颈。最后柒巫,愿各位 javaer ,合上電腦的剎那哈肖,有著俠客收劍入鞘的驕傲吻育!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市淤井,隨后出現(xiàn)的幾起案子布疼,更是在濱河造成了極大的恐慌,老刑警劉巖币狠,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件游两,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡漩绵,警方通過(guò)查閱死者的電腦和手機(jī)贱案,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)止吐,“玉大人宝踪,你說(shuō)我怎么就攤上這事“樱” “怎么了瘩燥?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)不同。 經(jīng)常有香客問(wèn)我厉膀,道長(zhǎng),這世上最難降的妖魔是什么二拐? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任服鹅,我火速辦了婚禮,結(jié)果婚禮上百新,老公的妹妹穿的比我還像新娘企软。我一直安慰自己,他們只是感情好饭望,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布仗哨。 她就那樣靜靜地躺著聚蝶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪藻治。 梳的紋絲不亂的頭發(fā)上碘勉,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音桩卵,去河邊找鬼验靡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛雏节,可吹牛的內(nèi)容都是我干的胜嗓。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼钩乍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼辞州!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起寥粹,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤变过,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后涝涤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體媚狰,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年阔拳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了崭孤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡糊肠,死狀恐怖辨宠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情货裹,我是刑警寧澤嗤形,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站泪酱,受9級(jí)特大地震影響派殷,放射性物質(zhì)發(fā)生泄漏还最。R本人自食惡果不足惜墓阀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拓轻。 院中可真熱鬧斯撮,春花似錦、人聲如沸扶叉。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至溢十,卻和暖如春垮刹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背张弛。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工荒典, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吞鸭。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓寺董,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親刻剥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子遮咖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345