JDK1.8內存佈局

一、內存佈局圖70)PS:左邊的區域屬於是在JVM劃分的內存之中,而右邊的則是直接在內存中。

在這裏插入圖片描述在這裏插入圖片描述

二、各部分詳解

對於每個線程來說,它都有程序計數器、Java虛擬機棧、本地方法棧,而這些都是線程私有的區域,不對外共享。

程序計數器:
程序計數器是一塊比較小的內存空間,可以看做是當前線程所執行的字節碼的行號指示器。(如果當前線程正在執行的是一個Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果正在執行的是一個Native方法,這個計數器值爲空。)這個地方也就是爲什麼我們能一行一行調試的原因。

Java虛擬機棧:
虛擬機棧描述的是Java方法執行的內存模型 : 每個方法執行的同時都會創建一個棧幀用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。每一個方法從調用直至執行完成的過程,就對應一個棧幀在虛擬機棧中入棧和出棧的過程。聲明週期與線程相同。(這就是我們通常意義上的棧,再詳細一點,是虛擬機棧中的局部變量表部分,當我們不涉及多線程的時候,往往只有一個主線程,方法調用的順序就是靠這個來的)我們在方法遞歸調用時,這可能拋出StackOverFlowError異常。

本地方法棧:
本地方法棧與虛擬機棧的作用完全一樣,他倆的區別無非是本地方法棧爲虛擬機使用的Native方法服務,而虛擬機棧爲JVM執行的Java方法服務。

還有線程共享的區域:Java堆、方法區、運行時常量池

Java堆
Java堆(Java Heap)是JVM所管理的最大內存區域。Java堆是所有線程共享的一塊區域,在JVM啓動時創建。此內存區域存放的都是對象實例
JVM規範中說到:“所有的對象實例以及數組都要在堆上分配”。Java堆是垃圾回收器管理的主要區域,因此很多時候可以稱之爲"GC堆"。根據JVM規範規定的內容,Java堆可以處於物理上不連續的內存空間中

ps:如果在堆中沒有足夠的內存完成實例分配並且堆也無法再拓展時,將會拋出OOM。

方法區(元數據區)
方法區與Java堆一樣,是各個線程共享的內存區域。它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。

ps:此區域的內存回收主要是針對常量池的回收以及對類型的卸載。當方法區無法滿足內存分配需求時,將拋出OOM異常。

直接內存
在JDK 1.4中新加入了NIO(New Input/Output)類,引入了一種基於通道(Channel)與緩衝區(Buffer)的I/O方式,它可以使用Native函數庫直接分配堆外內存,然後通過一個存儲在Java堆中的DirectByteBuffer對象作爲這塊內存的引用進行操作。這樣能在一些場景中顯著提高性能,因爲避免了在Java堆和Native堆中來回複製數據。

三、常量池補充

常量池可以分爲 Class文件常量池、運行時常量池、字符串常量池:

Class文件常量池
Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池(Constant Pool Table),用於存放編譯期生成的各種字面量和符號引用,這部分內容將在類加載後進入方法區的運行時常量池中存放。

運行時常量池
運行時常量池相對於Class文件常量池的另外一個重要特徵是具備動態性,Java語言並不要求常量一定只有編譯期才能產生,也就是並非預置入Class文件中常量池的內容才能進入方法區運行時常量池,運行期間也可能將新的常量放入池中,這種特性被開發人員利用得比較多的便是String類的intern()方法。

字符串常量池
存儲字符串對象,或是字符串對象的引用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章