java虛擬機在運行的時候會把內存分為不同的區域,每個區域都有其特定額用途。java虛擬機運行數據區如圖所示。
1、程序計數器
是一塊較小的內存空間,是當前線程所執行的字節碼的行號指示器。如果線程正在執行一個java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果是Naive方法,則計數器為空;這個區域不會出現OUtOfMemoryError異常。
java虛擬機多線程是使用線程輪流切換並分配處理執行時間的方式來實現的,在任何一個確定的時刻,一個處理器都只會執行一條線程中的指令。為了線程切換后能夠恢復到正確的執行位置,每條線程都需要一套獨立的線程計數器,這些計數器之間相互獨立,獨立存儲,這個內存區域為“線程私有”。
2、java虛擬機棧
java虛擬機棧也是線程私有,與線程的生命周期一致,在執行每個方法都會創建一個Stack Frame。每一個方法從開始執行到結束,對應一個Stack Frame在虛擬機值棧中從入棧和出棧的過程。如果線程請求的棧深度大於虛擬機所允許的深度,就會出現StackOverFlowException。如果允許動態擴展,在擴展的過程中,如果無法申請到足夠的內存,則會拋出OutOfMemoryException異常。
3、本地方法棧
和java虛擬機棧的作用類似,不同點在本地方法棧主要是為虛擬機使用到的Native方法提供服務,本地方法棧也會拋出StackOverFlowException和OutOfMemoryException異常。
4、java堆
堆是java虛擬機中內存中最大的一塊,被所有線程共享的一塊內存區域,在虛擬機創建時創建。作用就是存放對象實例,所有的對象的實例都需要在這里分配內存。幾乎所有的對象實例和對象數組都需要在堆上分配。是java虛擬機內存回收的管理的重要區域,因此也被稱為“GC”堆,可以被分為:新生代和老年代;Eden空間、From Survivor空間、To Survivor空間。如果堆中沒有內存完成實例分配,並且堆也無法擴展時,則拋出OutOfMemoryException異常
5、方法區
方法區和java堆一樣,是各個線程共享的內存區域,用於存儲被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯的代碼等數據。通常被開發人員成為“永久帶”。這個區域的內存回收的目標就是針對常亮池的回收和對類型的卸載,也是較為難處理的部分。