JVM运行时数据区
Java虛擬機在執行Java程序的過程中會把它所管理的內存劃分為若干個不同的數據區域。
1 方法區
簡單說方法區用來存儲類型的元數據信息,一個.class文件是類被java虛擬機使用之前的表現形式,一旦這個類要被使用,java虛擬機就會對其進行裝載、連接(驗證、準備、解析)和初始化,而裝載后的結果就是由.class文件轉變為方法區中的一段特定的數據結構。
(1)方法區存儲的信息
類型信息:全限定名、直接超類的全限定名、類的類型還是接口類型、訪問修飾符、直接超接口的全限定名的有序列表 字段信息:字段名、字段類型、字段的修飾符 方法信息:方法名、方法返回類型、方法參數的數量和類型(按照順序)、方法的修飾符 其他信息:除了常量以外的所有類(靜態)變量、一個指向ClassLoader的指針、一個指向Class對象的指針、常量池(常量數據以及對其他類型的符號引用)(2)永久代、元空間
方法區是java中的接?,永久代、元空間是具體實現類。
永久代,以前的方法區的實現,jdk8以后元空間代替了存在堆區。
元空間,1.8及以后方法區的實現,直接內存、OS內存。
(3)常量池
Java中的常量池,實際上分為兩種形態:靜態常量池和運行時常量池。
所謂靜態常量池,即*.class文件中的常量池,class文件中的常量池不僅僅包含字符串(數字)字面量,還包含類、方法的信息,占用class文件絕大部分空間。
運行時常量池,則是jvm虛擬機在完成類裝載操作后,將class文件中的常量池載入到內存中,并保存在方法區中,我們常說的常量池,就是指方法區中的運行時常量池。
2 本地方法棧
本地方法棧和java虛擬機棧差不多,唯一的區別是,java虛擬機棧為java虛擬機執行java服務,本地方法棧為虛擬機執行本地方法服務,也可以理解為 java調?c、c++的動態鏈接庫,運???的函數需要的棧。
3 程序計數器
程序計數器(Program Counter Register)是一塊較小的內存空間,它的作用可以看做是當前線程所執行的字節碼的行號指示器。在虛擬機的概念模型里(僅是概念模型,各種虛擬機可能會通過一些更高效的方式去實現),字節碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個計數器來完成。
由于Java虛擬機的多線程是通過線程輪流切換并分配處理器執行時間的方式來實現的,在任何一個確定的時刻,一個處理器(對于多核處理器來說是一個內核)只會執行一條線程中的指令。因此,為了線程切換后能恢復到正確的執行位置,每條線程都需要有一個獨立的程序計數器,各條線程之間的計數器互不影響,獨立存儲,我們稱這類內存區域為“線程私有”的內存。
4 虛擬機棧
Java虛擬機棧(Java Virtual Machine Stacks)也是線程私有的,它的生命周期與線程相同。虛擬機棧描述的是Java方法執行的內存模型:每個方法被執行的時候都會同時創建一個棧幀(Stack Frame)用于存儲局部變量表、操作棧、動態鏈接、方法出口等信息。每一個方法被調用直至執行完成的過程,就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程。
4.1 動態連接
虛擬機運行的時候,運行時常量池會保存大量的符號引用,這些符號引用可以看成是每個方法的間接引用。如果代表棧幀A的方法想調用代表棧幀B的方法,那么這個虛擬機的方法調用指令就會以B方法的符號引用作為參數,但是因為符號引用并不是直接指向代表B方法的內存位置,所以在調用之前還必須要將符號引用轉換為直接引用,然后通過直接引用才可以訪問到真正的方法。
如果符號引用是在類加載階段或者第一次使用的時候轉化為直接應用,那么這種轉換成為靜態解析。如果是在運行期間轉換為直接引用,那么這種轉換就成為動態連接。
4.2 局部變量表
局部變量表是一組變量值存儲空間,用于存放方法參數和方法內部定義的局部變量。
4.3 操作數棧
操作數棧 和局部變量區一樣,操作數棧也是被組織成一個以字長為單位的數組。但是和前者不同的是,它不是通過索引來訪問,而是通過標準的棧操作——壓棧和出?!獊碓L問的。比如,如果某個指令把一個值壓入到操作數棧中,稍后另一個指令就可以彈出這個值來使用。
4.4 返回地址
方法的返回分為兩種情況,不過無論是那種方式的方法結束,在退出當前方法時都會跳轉到當前方法被調用的位置。
(1)一種是正常退出,退出后會根據方法的定義來決定是否要傳返回值給上層的調用者。
(2)一種是異常導致的方法結束,這種情況是不會傳返回值給上層的調用方法。
5 堆
對于大多數應用來說,Java堆(Java Heap)是Java虛擬機所管理的內存中最大的一塊。Java堆是被所有線程共享的一塊內存區域,在虛擬機啟動時創建。此內存區域的唯一目的就是存放對象實例,幾乎所有的對象實例都在這里分配內存。
堆大小 = 新生代 + 老年代。其中,堆的大小可以通過參數 –Xms、-Xmx 來指定。
新生代如何進入老年代
(1) 大對象直接進入年老代
對象大小超過Eden區的一半直接進入年老代。
(2) 長期存活的對象將進入年老代
虛擬機給每個對象定義了一個對象年齡計數器,在對象在Eden創建并經過第一次Minor GC后仍然存活,并能被Suivivor容納的話,將會被移動到Survivor空間,并對象年齡設置為1。每經歷過Minor GC,年齡就增加1歲,當到一定程度(默認15歲,可以通過參數-XXMaxTenuringThreshold設置),就將會晉升年老代。
(3) 動態對象年齡判定
了更好地適應不同程序內存狀況,虛擬機并不硬性要求對象年齡達到MaxTenuringThreshold才能晉升老年代,如果在Survivor空間中相同年齡所有對象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對象就可以直接進入年老代。
(4)空間分配擔保
當Eden和一個Survivor區中依然存活的對象無法放入到Survivor中,則通過分配擔保機制提前轉移到老年代中。
總結
- 上一篇: ibm服务器vios系统,IBM VIO
- 下一篇: 安卓打开cbr文件_什么是CBR和CBZ