JVM內存結構分析

  對於Java程序員來講,內存是由JVM自動管理的,因此一旦出現內存泄漏或溢出的問題,不瞭解JVM的內存結構和各個內存區域的工做職責,將對解決問題帶來很大的麻煩,本文參照周志明的《深刻理解Java虛擬機》,介紹JVM內存結構,比較枯燥,但對知其然,不知因此然的編碼人員來講仍是有必定幫助的。html

  按照Java虛擬機規範的規定,JVM自動管理的內存將會包括如下幾個運行時數據區域。java

 

  JVM內存結構分析

 

  程序計數器程序員

  程序計數器(Program Counter Register)是JVM中一塊較小的內存區域,保存着當前線程執行的虛擬機字節碼指令的內存地址。Java多線程的實現,實際上是經過線程間的輪流切換並分配處理器執行時間的方式來實現的,在任什麼時候刻,處理器都只會執行一個線程中的指令。在多線程場景下,爲了保證線程切換回來後,還能恢復到原先狀態,找到原先執行的指令,因此每一個線程都會設立一個程序計數器,而且各個線程之間不會互相影響,程序計數器爲"線程私有"的內存區域。數據結構

  若是當前線程正在執行Java方法,則程序計數器保存的是虛擬機字節碼的內存地址,若是正在執行的是Native方法(非Java方法,JVM底層有許多非Java編寫的函數實現),計數器則爲空。程序計數器是惟一一個在Java規範中沒有規定任何OutOfMemory場景的區域。多線程

  虛擬機棧函數

  虛擬機棧(Java Virtual Machine Stacks)和線程是緊密聯繫的,每建立一個線程時就會對應建立一個Java棧,因此Java棧也是"線程私有"的內存區域,這個棧中又會對應包含多個棧幀,每調用一個方法時就會往棧中建立並壓入一個棧幀,棧幀是用來存儲方法數據和部分過程結果的數據結構,每個方法從調用到最終返回結果的過程,就對應一個棧幀從入棧到出棧的過程。編碼

  虛擬機棧是一個後入先出的數據結構,線程運行過程當中,只有一個棧幀是處於活躍狀態的,被稱爲"當前活動幀棧",當前活動幀棧始終是虛擬機棧的棧頂元素。線程

 

  JVM內存結構分析

 

  本地方法棧htm

  本地方法棧(Native Method Stack)和虛擬機棧的做用類似,不過虛擬機棧是爲Java方法服務的,而本地方法棧是爲Native方法服務的。對象

  方法區

  方法區(Method Area)是用於存儲類結構信息的地方,包括常量池、靜態變量、構造函數等類型信息,類型信息是由類加載器在類加載時從類文件中提取出來的。

  方法區一樣存在垃圾收集,由於用戶經過自定義加載器加載的一些類一樣會成爲垃圾,JVM會回收一個未被引用類所佔的空間,以使方法區的空間達到最小。

  方法區中還存在着常量池,常量池包含着一些常量和符號引用(加載類的鏈接階段中的解析過程會將符號引用轉換爲直接引用)。

  方法區是線程共享的。

  堆

  堆(heap)是存儲java實例或者對象的地方,是GC的主要區域,一樣是線程共享的內存區域。

  案例分析一

 

 JVM內存結構分析

 

  案例分析二

 

  JVM內存結構分析

JVM內存結構分析

 

  上面main方法中運行的程序過程以下:

  (1)用戶建立了一個Student對象,運行時JVM首先會去方法區尋找該對象的類型信息,沒有則使用類加載器classloader將Student.class字節碼文件加載至內存中的方法區,並將Student類的類型信息存放至方法區。

  (2)接着JVM在堆中爲新的Student實例分配內存空間,這個實例持有着指向方法區的Student類型信息的引用,引用指的是類型信息在方法區中的內存地址。

  (3)在此運行的JVM進程中,會首先起一個線程跑該用戶程序,而建立線程的同時也建立了一個虛擬機棧,虛擬機棧用來跟蹤線程運行中的一系列方法調用的過程,每調用一個方法就會建立並往棧中壓入一個棧幀,棧幀用來存儲方法的參數,局部變量和運算過程的臨時數據。上面程序中的stu是對Student的引用,就存放於棧中,並持有指向堆中Student實例的內存地址。

  (4)JVM根據stu引用持有的堆中對象的內存地址,定位到堆中的Student實例,因爲堆中實例持有指向方法區的Student類型信息的引用,從而得到add()方法的字節碼信息,接着執行add()方法包含的指令。

  總結

  一、全部線程共享的內存數據區:方法區,堆。而虛擬機棧,本地方法棧和程序計數器都是線程私有的。

  二、存放於棧中的東西以下:

  2.1每一個線程包含一個棧區,棧中只保存基礎數據類型的對象和自定義對象的引用(不是對象)。對象都存放在堆區中。

  2.2每一個棧中的數據(基礎數據類型和對象引用)都是私有的,其餘棧不能訪問。

  2.3方法的形式參數,方法調用完後從棧空間回收

  2.4引用對象的地址,引用完後,棧空間地址當即被回收,堆空間等待GC

  三、存放於堆中的東西以下:

  3.1存儲的所有是對象,每一個對象包含一個與之對應的class信息

  3.2 Jvm只有一個堆區(heap)被全部線程共享,堆區中不存放基本類型和對象引用,只存放對象自己

  四、存放於方法區中的東西以下:

  4.1存放線程所執行的字節碼指令

  4.2跟堆同樣.被全部線程共享.方法區包含:全部的class和static變量

  4.3常量池位於方法區中,見以下圖示說明

 

JVM內存結構分析

相關文章
相關標籤/搜索