java虛擬機會在執(zhí)行程序的過程中把管理的內存劃分成幾個數(shù)據(jù)區(qū):程序計數(shù)器敢艰、java 虛擬機棧震嫉、本地方法棧湃望、java堆瞳浦、方法區(qū)。?
1、程序計算器:
這個比較好理解傻咖,就是線程執(zhí)行字節(jié)碼的行標孙援,就是用來記錄程序執(zhí)行到哪里了,這樣程序才知道接下來應該運行哪里崭放。因為是為每個線程記錄了,所以比較理所當然的就是線程私有啦。
這個計算器的值也很好理解祝懂,如果是執(zhí)行的是Java代碼盆色,記錄的就是字節(jié)碼指令地址;如果執(zhí)行是native方法(大概就是一個java調用的非java的接口),那計數(shù)器就是空值。
這個計算器還有一個特點就是唯一一個java虛擬機規(guī)范沒有規(guī)定任何OutOfMemoryError情況的區(qū)域。
2蓉冈、java 虛擬機棧:
虛擬機棧其實就是java方法執(zhí)行的內存模塊,方法的運行的這個過程就是對應一個棧幀(方法在執(zhí)行的同時會創(chuàng)建一個棧幀用于存儲局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息)從虛擬機棧進棧出棧的過程分歇。這部分也是線程私有的欧漱。
java虛擬機規(guī)范對虛擬機棧規(guī)定了兩種的異常情況:
1)線程請求棧的深度大于java虛擬機規(guī)范規(guī)定的深度职抡,這時會拋出StackOverFlowError異常缚甩。
2)當虛擬機棧動態(tài)拓展時(大部分虛擬機是允許的),拓展時無法申請到足夠的內存,這時會拋出OutOfMemoryError異常驾窟。
3杉畜、本地方法棧 :
與虛擬機棧很類似,主要的區(qū)別在于本地方法棧是為虛擬機使用到Native方法服務的衷恭。但是java虛擬機規(guī)范并沒有強制對本地方法棧進行規(guī)定,所以有一些虛擬機甚至會把虛擬機棧和本地方法棧合二為一。
4窗看、java堆:
一般情況下茸歧,java堆是java虛擬機管理中的最大一塊。java堆在java虛擬機啟時創(chuàng)建显沈,是被所有線程共享的软瞎,是大多數(shù)的實例都要在這里分配內存的(棧上分配和標量替換導致一些實例不在堆上分配)。是垃圾收集器管理的主要區(qū)域。
java虛擬機規(guī)范規(guī)定铜涉,java堆只需要內存是邏輯連續(xù)的就可以智玻,不一定是要物理連續(xù)(主流虛擬機通過-Xmx和-Xms來控制java堆的拓展)。拓展時無法申請到足夠的內存芙代,這時會拋出OutOfMemoryError異常吊奢。
5、方法區(qū):
這部分的作用主要用于存儲已經(jīng)被虛擬機加載的類信息页滚、常量、靜態(tài)變量铺呵、即時編譯器編譯后的代碼裹驰。這部分是被所有線程共享的。
java虛擬機規(guī)范規(guī)定片挂,方法區(qū)也是只需要內存是邏輯連續(xù)的就可以幻林,不一定是要物理連續(xù),可以動態(tài)拓展整葡,并且可以選擇不實現(xiàn)垃圾收集。雖然這部分實現(xiàn)垃圾收集效果并不好旬渠,但是也是有必要的俱萍。如果沒有垃圾收集,可能會出現(xiàn)內存泄漏的情況告丢。拓展時無法申請到足夠的內存鼠次,這時會拋出OutOfMemoryError異常。
方法區(qū)有一個部分叫運行時常量池芋齿。java虛擬機規(guī)范規(guī)定并沒有對運行時常量池作任何細節(jié)的要求。運行時常量池具有動態(tài)性成翩,預置在Class文件中常量池的內容能進入運行時常量池觅捆,運行期間的新的常量也是可能將加入。