JVM內(nèi)存模型
之前看過很多關(guān)于jvm內(nèi)存模型的文章,什么有堆棧,方法區(qū),程序計數(shù)器等劃分,也有文章說主存和工作內(nèi)存的模型。
這里我覺得無論是jvm內(nèi)存區(qū)域的劃分,還是主存工作內(nèi)存的使用,都是屬于jvm內(nèi)存模型內(nèi)的知識?;谧约旱睦斫?,簡單總結(jié)一下,單純只是個人總結(jié),不一定是正確的,假如看到有錯誤的地方可以幫忙指出。
jvm運(yùn)行期的內(nèi)存區(qū)域劃分:

上述圖可以比較直觀的看出jvm運(yùn)行期,哪些內(nèi)存區(qū)域?qū)儆诠蚕淼?,哪些屬于線程私有的。下面簡單的介紹每個內(nèi)存區(qū)域:
1.線程私有的內(nèi)存區(qū)域:
(1)java 棧(jvm stack)
主要存放一個個棧幀,每個棧幀對應(yīng)著線程執(zhí)行每個方法相關(guān)的數(shù)據(jù)(局部變量表,操作棧,動態(tài)鏈接,方法出口等信息),每一個方法執(zhí)行完了,對應(yīng)的棧幀就會從java棧出棧。當(dāng)棧的深度達(dá)到j(luò)vm所允許的最大深度,就會拋出 stackoverflowerror 的錯誤,當(dāng)擴(kuò)展無法申請到足夠的內(nèi)存則會拋出 outofmemoryerror 的錯誤。
(2)程序計數(shù)器(PC register)
很小的內(nèi)存空間,因為jvm底層執(zhí)行程序是執(zhí)行字節(jié)碼指令,而程序計數(shù)器就記錄著當(dāng)前指令的執(zhí)行位置。隨著指令執(zhí)行而變化,從而獲取下一個需要執(zhí)行的指令(可實現(xiàn)分支,循環(huán),跳轉(zhuǎn),異常)。
(3)本地方法棧(native method stack)
與java棧存儲內(nèi)容很相似,只是java棧是服務(wù)于java方法(字節(jié)碼),而本地方法棧是服務(wù)于native方法。同樣也會拋出上面提到的異常錯誤。
2.線程共享的內(nèi)存區(qū)域:
(1)堆(heap)
這一塊主要是存放對象數(shù)據(jù),是jvm內(nèi)存中最大的一塊。包含了新生代和年老代,也是GC(垃圾回收)主要收集的區(qū)域。(GC算法會在后面的文章里提到),當(dāng)內(nèi)存申請超過了jvm定義的內(nèi)存大小,則會報outofmemory的錯誤。
(2.1)本地方法區(qū)(Method Area)
主要存放的是類信息,常量,靜態(tài)變量等數(shù)據(jù),在jdk1.8之前,hotspot里是將方法區(qū)當(dāng)做永久代來使用,之后廢除了永久代,這里會在另外一篇文章里解釋。
(2.2)運(yùn)行時常量池(Runtime Constant Pool)
屬于方法區(qū)的一部分,用于存放編譯期生成的各種字面量和符號引用,如字符串,final變量,類名和方法名常量等(這里需要注意常量池的常量的存儲大?。?/p>