Java與c++之間有一堵由內存動態分配和垃圾收集技術所圍成的“高牆”,牆外的人想進去,牆里面的人卻想出來。
—— 《深入理解Java虛擬機》 周志明
對於c++來說 , 在內存管理領域,他們既是擁有最高權利的皇帝,又是從事最基礎工作的勞動人民。他們擁有每一個對象的
所有權,又背負着維護每一個對象的責任。
而對於Java程序員來說,在JVM的幫助下,不再需要為每一個new 操作去寫配對的delete / free 代碼,不容易出現內存泄漏
和內存溢出的問題。
那么就然我們來一探JVM的底層結構吧~
上圖就是JVM的結構啦~ 那么下面就讓我來 一 一 介紹 每塊區域的職責和特點
當我們把java程序寫出來的時候,首先要對它進行編譯才可以運行,比如上圖的Math類,我們要首先用javac指令
把它編譯生成字節碼文件( .class ) , 然后就可以運行了,而運行時的內存管理就依賴於JVM,由JVM對我們的內存
進行管理。
程序計數器:
想必學過計算機組成原理的同學對程序計數器都不陌生吧~ 它負責記錄我們的代碼運行到哪一行,以及負責一些流程控制。
字節碼解釋器工作時會通過改變計數器的值來選去下一條指令,分支,循環,跳轉,異常處理,線程恢復都需要計數器。
每條線程都需要一個獨立計數器,各線程計數器互不影響,這類內存區域稱為“線程私有”內存。
棧(線程):
線程私有,生命周期與線程相同。
每個方法在執行的時候會創建一個棧幀 用於存儲 局部變量表 、 操作數棧 、 動態鏈接 、 方法出口
每一個方法從調用直到執行完成的過程,就對應一個棧幀在虛擬機中入棧到出棧的過程。
局部變量表: 存放各種基本數據類型 ( boolean , byte , char , short , int , float , long , double ) 沒有 String!
對象引用 ( 指向對象起始地址的指針 )
return Address 類型 (指向一條字節碼指令的地址)
它有哪些異常呢? 有:線程請求的棧深度大於JVM所允許,StackOverflowError
若棧可以動態擴展,無發申請到足夠內存時,OutOfMemoryError
本地方法棧:
與虛擬機棧區別:虛擬機棧為JVM執行Java方法服務
方法棧為JVM使用到的Native方法服務
也會拋出StackOverflowError, OutOfMemoryError
堆:
內存最大 被所有線程共享
幾乎所有的對象實例和數組都要在堆中分配內存(除了靜態等)
若在堆中沒有內存完成實例分配,且堆無法擴展時,拋出OutOfMemoryError
方法區:
各線程共享
用於存儲類信息,常量,靜態變量,編譯后的代碼
垃圾收集很少出現
運行時常量池:
方法區的一部分
存放編譯期生成的各種字面量和符號引號(常量池)
這部分內容在類加載后進入方法區的運行時常量池中存放
直接內存:
不是JVM運行時數據區的一部分,也不是JVM規范中定義的內存區域
那么今天的JVM就介紹到這里~
下一次我會介紹JVM是如何創建對象的哦~