
程式計數器:
目前線程執行行的行号訓示器,Java虛拟機多線程通過輪流切換并配置設定處理器執行時間,
一個處理器(對于多和處理器來說是一個核心)都隻會一條線程中的指令,為了線程切
換後能恢複到正确的執行位置,每條線程都需要一條獨立的程式計數器,線程之間計數
器互不引響,獨立存儲,稱為線程私有記憶體。虛拟機規範中唯一沒有規定OOM.
虛拟機棧:
線程私有,為虛拟機執行java方法(位元組碼)服務生命周期與線程相同,虛拟機棧描述的
是java方法執行的記憶體子產品:每個方法執行同時會建立一個棧幀用于存儲局部變量表、操
作數棧、動态連結、方法出口等,每一個方法從調用到執行完成過程,對應着一個棧幀在
虛拟機棧中入棧到出棧的過程,規定兩種異常:線程請求的棧深度大于虛拟機所允許的深
度,将抛出StackOverflowError異常,如果虛拟機可動态擴充(目前大部分java虛拟機都
可動态擴充,隻不過java虛拟機規範中也允許固定長度的虛拟機棧),如果擴充時無法申
請到足夠記憶體時,就會抛出OOM.
本地方法棧:
與虛拟機棧發揮的作用非常相似,為虛拟機使用到的Native方法服務,虛拟機規範中對本
地方法棧使用的語言、方式與資料結構沒有強制規定,Sun HostSpot虛拟機把虛拟機棧和
本地方法棧合二為一,本地方法棧區域也會報StackOverflowError和OOM異常
Java堆:
java堆是所有線程共享的一塊記憶體區域,在虛拟機啟動時建立,此記憶體唯一目的就是存放
執行個體對象,幾乎所有的執行個體對象及數組都要在推上配置設定記憶體,對于大多數應用來說java堆
是虛拟機中管理記憶體最大的一塊,java堆是垃圾收集器管理的主要區域,也被稱為GC堆,
從記憶體回收的角度看,由于現代收集器都采用分代收機算法,是以堆中還可以細分為:新
生代和老年代,再細緻一點有Eden空間、From Survivor空間、To Survivor空間,從記憶體
配置設定的角度來看,線程共享的java堆中可能劃分出多個線程私有的配置設定緩沖區,不過無論
怎麼劃分都與存放内容無關,存放的仍然都是對象執行個體,進一步劃分的目的是為了更好的
回收記憶體,或者更快的配置設定記憶體,記憶體大小既可以固定也可以擴充,可通過Xmx和Xms控制,
如果在堆中沒有記憶體完成執行個體配置設定、也無法再擴充将會報出OOM異常。
方法區:
方法區和java堆一樣,是所有線程共享的記憶體區域,它用于存儲被虛拟機加載的類資訊、
常類、靜态變量、即時編譯器編譯後的代碼等資料,在虛拟機規範中方法區被描述為堆的
一個邏輯部分,它有一個别名叫非對,對于習慣在HotSpot虛拟機上開發、部署的開發者來
說,很多人稱方法區為“永久代(permanent Generation)”本質上兩者不等價,永久代有
-XX:MaxPermSize上限容易造成記憶體溢出,方法區無法滿足記憶體配置設定需求時,将抛出OOM異常。
運作時常量池:
運作時常量池是方法區的一部分,class檔案中除了有類的版本、字段、方法、接口等,還有
一項常量池(Constant Pool Table)用于存放編譯器生成的各種字面量和符号引用,這部分
内容将在類加載後進入方法區的運作時常量池存放,運作時常量池受到方法區記憶體的限制,當
常量池無法申請到記憶體時将抛出OOM異常。
直接記憶體:
不在運作時資料區内,不受Java堆記憶體限制,會受到本機總記憶體限制,同樣會抛出OOM異常。