JVM學習記錄—內存模型

 目錄

什麼是Java虛擬機

JVM內存模型

 程序計數器

方法區

虛擬機棧

本地方法棧


本文是基於Java8的HotSpot虛擬機分析的 

什麼是Java虛擬機

衆所周知,java主要特點就是平臺無關性。那麼如何實現平臺無關性呢,答案就是用虛擬機將不同操作系統的差異隔離。Java 之所以要在虛擬機中運行,是因爲它提供了可移植性。Java 代碼被編譯爲 Java 字節碼,可以在不同平臺上的 Java 虛擬機實現上運行。

JVM內存模型

JVM(Java Virtual Machine)將管理的內存劃分爲不同功能的內存區域,如下圖。

一段Java代碼的運行過程:類文件編譯後生成的class文件通過類加載器class loader加載到JVM中, 然後程序計數器記錄目前執行到了哪一條字節碼指令,然後MetaSpace存放了類的相關信息(1.8以前叫方法區),再將操作的棧幀(局部變量)存放在虛擬機棧中,創建的對象實例會存儲在堆中。

其中方法區和堆是線程共享的

程序計數器和虛擬機棧、本地方法棧是線程私有的

 

public class Hello {
	public static void main(String[] args) {
		Say say=new Say();
		say.say();
	}
}
class Say{
	public void say(){
		System.out.println("hello!");
	}
}

上邊這一段代碼是舉的一個例子,後邊將以這個例子來具體說下每個內存區域都存儲了什麼信息。 

 程序計數器

程序計數器就是用來記錄當前執行的字節碼指令的位置的,也就是記錄目前執行到了哪一條字節碼指令。就是Hello.java文件編譯後生成的.class文件的字節碼文件。

方法區

在一個jvm實例的內部,類型信息被存儲在一個稱爲方法區的內存邏輯區中。類型信息是由類加載器在類加載時從類文件中提取出來的。類(靜態)變量也存儲在方法區中。

類型信息
對每個加載的類型,jvm必須在方法區中存儲以下類型信息: 

  • 這個類型的完整有效名 
  • 這個類型直接父類的完整有效名(除非這個類型是interface或是  java.lang.Object,兩種情況下都沒有父類) 
  • 這個類型的修飾符(public,abstract, final的某個子集) 
  • 這個類型直接接口的一個有序列表 

除了以上的基本信息外,jvm還要爲每個類型保存以下信息: 
類型的常量池( constant pool) 
域(Field)信息 
方法(Method)和返回值信息 
除了常量外的所有靜態(static)變量 

虛擬機棧

虛擬機棧是用來保存每個方法內的局部變量等數據,每個線程都有自己的虛擬機棧。如果線程中執行了一個方法,就會對這個方法創建對應的一個棧幀。棧幀裏就有了這個方法的局部變量、方法出口等等數據。

堆是用來存放創建的各種對象。例如Say()對象實例,引用的圖例如下。堆中有分爲新生代、老年代等等,這個涉及到GC(垃圾回收)具體回頭單獨開一篇說。

本地方法棧

本地方法棧的功能和特點類似於虛擬機棧,均具有線程隔離的特點以及都能拋出StackOverflowError和OutOfMemoryError異常。不同的是,本地方法棧服務的對象是JVM執行的native方法,而虛擬機棧服務的是JVM執行的java方法。如何去服務native方法?native方法使用什麼語言實現?怎麼組織像棧幀這種爲了服務方法的數據結構?虛擬機規範並未給出強制規定,因此不同的虛擬機實可以進行自由實現,我們常用的HotSpot虛擬機選擇合併了虛擬機棧和本地方法棧。


下圖是整個jvm完整的執行流程圖 

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