Java 虛擬機的內存空間分爲 5 個部分:算法
JDK 1.8 同 JDK 1.7 比,最大的差異就是:元數據區取代了永久代。元空間的本質和永久代相似,都是對 JVM 規範中方法區的實現。不過元空間與永久代之間最大的區別在於:元數據空間並不在虛擬機中,而是使用本地內存。服務器
程序計數器是一塊較小的內存空間,是當前線程正在執行的那條字節碼指令的地址。若當前線程正在執行的是一個本地方法,那麼此時程序計數器爲Undefined
。多線程
OutOfMemoryError
的內存區域。Java 虛擬機棧是描述 Java 方法運行過程的內存模型。jvm
Java 虛擬機棧會爲每個即將運行的 Java 方法建立一塊叫作「棧幀」的區域,用於存放該方法運行過程當中的一些信息,如:性能
當方法運行過程當中須要建立局部變量時,就將局部變量的值存入棧幀中的局部變量表中。spa
Java 虛擬機棧的棧頂的棧幀是當前正在執行的活動棧,也就是當前正在執行的方法,PC 寄存器也會指向這個地址。只有這個活動的棧幀的本地變量能夠被操做數棧使用,當在這個棧幀中調用另外一個方法,與之對應的棧幀又會被建立,新建立的棧幀壓入棧頂,變爲當前的活動棧幀。線程
方法結束後,當前棧幀被移出,棧幀的返回值變成新的活動棧幀中操做數棧的一個操做數。若是沒有返回值,那麼新的活動棧幀中操做數棧的操做數沒有變化。code
因爲Java 虛擬機棧是與線程對應的,數據不是線程共享的,所以不用關心數據一致性問題,也不會存在同步鎖的問題。
Java 虛擬機棧會出現兩種異常:StackOverFlowError 和 OutOfMemoryError。對象
若 Java 虛擬機棧的大小不容許動態擴展,那麼當線程請求棧的深度超過當前 Java 虛擬機棧的最大深度時,拋出 StackOverFlowError 異常。blog
若容許動態擴展,那麼當線程請求棧時內存用完了,沒法再動態擴展時,拋出 OutOfMemoryError 異常。
出現 StackOverFlowError 時,內存空間可能還有不少。
本地方法棧是爲 JVM 運行 Native 方法準備的空間,因爲不少 Native 方法都是用 C 語言實現的,因此它一般又叫 C 棧。它與 Java 虛擬機棧實現的功能相似,只不過本地方法棧是描述本地方法運行過程的內存模型。
本地方法被執行時,在本地方法棧也會建立一塊棧幀,用於存放該方法的局部變量表、操做數棧、動態連接、方法出口信息等。
方法執行結束後,相應的棧幀也會出棧,並釋放內存空間。也會拋出 StackOverFlowError 和 OutOfMemoryError 異常。
若是 Java 虛擬機自己不支持 Native 方法,或是自己不依賴於傳統棧,那麼能夠不提供本地方法棧。若是支持本地方法棧,那麼這個棧通常會在線程建立的時候按線程分配。
堆是用來存放對象的內存空間,幾乎全部的對象都存儲在堆中。
不一樣的區域存放不一樣生命週期的對象,這樣能夠根據不一樣的區域使用不一樣的垃圾回收算法,更具備針對性。
堆的大小既能夠固定也能夠擴展,但對於主流的虛擬機,堆的大小是可擴展的,所以當線程請求分配內存,但堆已滿,且內存已沒法再擴展時,就拋出 OutOfMemoryError 異常。
Java 堆所使用的內存不須要保證是連續的。而因爲堆是被全部線程共享的,因此對它的訪問須要注意同步問題,方法和對應的屬性都須要保證一致性。
Java 虛擬機規範中定義方法區是堆的一個邏輯部分。方法區存放如下信息:
方法區是堆的一個邏輯部分,所以和堆同樣,都是線程共享的。整個虛擬機中只有一個方法區。
方法區中的信息通常須要長期存在,並且它又是堆的邏輯分區,所以用堆的劃分方法,把方法區稱爲「永久代」。
方法區中的信息通常須要長期存在,回收一遍以後可能只有少許信息無效。主要回收目標是:對常量池的回收;對類型的卸載。
和堆同樣,容許固定大小,也容許動態擴展,還容許不實現垃圾回收。
方法區中存放:類信息、常量、靜態變量、即時編譯器編譯後的代碼。常量就存放在運行時常量池中。
當類被 Java 虛擬機加載後, .class 文件中的常量就存放在方法區的運行時常量池中。並且在運行期間,能夠向常量池中添加新的常量。如 String 類的 intern() 方法就能在運行期間向常量池中添加字符串常量。
直接內存是除 Java 虛擬機以外的內存,但也可能被 Java 使用。
在 NIO 中引入了一種基於通道和緩衝的 IO 方式。它能夠經過調用本地方法直接分配 Java 虛擬機以外的內存,而後經過一個存儲在堆中的DirectByteBuffer
對象直接操做該內存,而無須先將外部內存中的數據複製到堆中再進行操做,從而提升了數據操做的效率。
直接內存的大小不受 Java 虛擬機控制,但既然是內存,當內存不足時就會拋出 OutOfMemoryError 異常。
服務器管理員在配置虛擬機參數時,會根據實際內存設置-Xmx
等參數信息,但常常忽略直接內存,使得各個內存區域總和大於物理內存限制,從而致使動態擴展時出現OutOfMemoryError
異常。