分享一波:程序員賺外快-必看的巔峰干貨
據 JVM 規范,JVM 內存結構共分為虛擬機棧、堆、方法區、程序計數器、本地方法棧五個部分。這里的java內存結構與前面所述的Java內存模型是兩個概念,不可以混淆。
堆
java堆是java虛擬機所管理的內存中最大的一塊,是被所有線程共享的一塊內存區域,在虛擬機啟動時創建。此內存區域的唯一目的就是存放對象實例,這一點在Java虛擬機規范中的描述是:所有的對象實例以及數組都要在堆上分配(從這一特性上來說,數組其實也算是一種對象)。
java堆是垃圾收集器管理的主要區域,因此也被成為“GC堆”。從內存回收角度來看java堆可分為:新生代和老生代。從內存分配的角度看,線程共享的Java堆中可能劃分出多個線程私有的分配緩沖區。無論怎么劃分,都與存放內容無關,無論哪個區域,存儲的都是對象實例,進一步的劃分都是為了更好的回收內存,或者更快的分配內存。
根據Java虛擬機規范的規定,java堆可以處于物理上不連續的內存空間中。當前主流的虛擬機都是可擴展的(通過 -Xmx 和 -Xms 控制)。如果堆中沒有內存完成實例分配,并且堆也無法再擴展時,將會拋出OutOfMemoryError異常。
虛擬機棧
java虛擬機也是線程私有的,它的生命周期和線程相同。虛擬機棧描述的是Java方法執行的內存模型:每個方法在執行的同時都會創建一個棧幀(Stack Frame)用于存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。
咱們常說的堆內存、棧內存中,棧內存指的就是虛擬機棧。局部變量表存放了編譯期可知的各種基本數據類型(8個基本數據類型)、對象引用(地址指針)、returnAddress類型。
局部變量表所需的內存空間在編譯期間完成分配。在運行期間不會改變局部變量表的大小。
這個區域規定了兩種異常狀態:如果線程請求的棧深度大于虛擬機所允許的深度,則拋出StackOverflowError異常;如果虛擬機棧可以動態擴展,在擴展是無法申請到足夠的內存,就會拋出OutOfMemoryError異常。
本地方法棧
本地方法棧與虛擬機棧所發揮作用非常相似,它們之間的區別不過是虛擬機棧為虛擬機執行Java方法(也就是字節碼)服務,而本地方法棧則為虛擬機使用到的native方法服務。本地方法棧也是拋出兩個異常。
方法區
方法區與java堆一樣,是各個線程共享的內存區域,它用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。它有個別命叫Non-Heap(非堆)。當方法區無法滿足內存分配需求時,拋出OutOfMemoryError異常。
運行時常量池
運行時常量池是方法區的一部分。Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池,用于存放編譯期生成的各種字面量和符號引用,這部分內容將在加載后進入方法區的運行時常量池中存放。
程序計數器
程序計數器是一塊較小的內存空間,它可以看作是當前線程所執行的字節碼的行號指示器。
由于Java虛擬機的多線程是通過線程輪流切換并分配處理器執行時間的方式來實現的,一個處理器都只會執行一條線程中的指令。因此,為了線程切換后能恢復到正確的執行位置,每條線程都有一個獨立的程序計數器,各個線程之間計數器互不影響,獨立存儲。稱之為“線程私有”的內存。程序計數器內存區域是虛擬機中唯一沒有規定OutOfMemoryError情況的區域。
*************************************優雅的分割線 **********************************
分享一波:程序員賺外快-必看的巔峰干貨
如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程
請關注微信公眾號:HB荷包
一個能讓你學習技術和賺錢方法的公眾號,持續更新