1. 程式人生 > >JVM知識總結-運行時區域劃分

JVM知識總結-運行時區域劃分

深入理解 部分 緩沖區 inter 滿足 計數 新的 地址 字面量

區域簡介

JVM運行時區域有些隨著虛擬機進程的啟動而存在,有些依賴於用戶線程的啟動和結束而建立和銷毀,大致分為以下幾類:方法區虛擬機棧本地方法棧程序計數器,概念圖如下(源於《深入理解JAVA虛擬機-JVM高級特性》):

技術分享圖片

程序計數器

  1. 當前線程所執行的字節碼的行號指示器,是一塊各個線程私有的內存,每個線程都有一個獨立的程序計數器;
  2. 如果線程執行的是一個JAVA方法,計數器記錄的是虛擬機字節碼指令的地址,如果執行的是一個Native方法,計數器值為空(Undefined);
  3. 唯一一個在JVM規範中沒有規定任何OOM情況的區域;

虛擬機棧

  1. 線程私有,每個線程執行時會創建一個棧楨(Stack Frame),包括局部變量表、操作數棧、動態鏈接、方法出口等信息,一個方法的調用過程對應著一個棧楨在虛擬機棧中的入棧和出棧操作;
  2. 局部變量表:存放了編譯期可知的各種基本數據類型(byte、short、char、int、long、float、double、boolean),對象引用(reference),returnAddress類型(指向了一條字節碼指令的地址),64位的long和double占用兩個Slot(局部變量空間),其他占用一個,局部變量表所需空間在編譯期就確定
  3. JVM規範中這個區域有兩種異常情況,如果線程請求的棧深度大於虛擬機所允許的深度--拋出StackOverflowError,如果虛擬機棧可動態擴展但擴展時申請的內存無法滿足--拋出OutOfMerroyError;

本地方法棧

與虛擬機棧作用類似,區別在於本地方法棧用於執行Native方法

,JVM規範並未對此區域的實現做強制規定,具體的虛擬機可自由實現,此區域也會拋出StackOverflowError和OutOfMerroyError;

  1. 所有線程共享的區域,幾乎所有的對象實例都在這裏分配內存,之所以是幾乎,是因為JIT的優化技術已經使得部分對象實例不必在堆上分配;
  2. 從內存分配的角度看,堆中可能劃分出多個線程私有的分配緩沖區(Thread Local Allocation Buffer),目的是為了更好回收內存或更快的分配內存;
  3. 邏輯上連續,物理上可以不連續;
  4. 當堆中沒有足夠的內存完成對象實例的分配,且無法再擴展,會拋出OOM;

方法區

  1. 線程共享區域,用於存儲已被虛擬機加載的類信息、常量、靜態變量、JIT產生的代碼等數據;
  2. HotSpot將永久代(Permanent Generation)作為方法區的實現,但本質上與方法區並不等價;
  3. 不需要連續的內存,可擴展,可以選擇不實現垃圾收集(GC只是hotspot在此區域實現的功能),當無法滿足內存分配需求時,會拋出OOM;
  4. 運行時常量池:Class文件中的常量池--用於存放編譯期生成的各種字面量和符號引用--將在類加載後進入方法區的運行時常量池,除此之外還會把翻譯出來的直接引用也存入,相對於Class文件常量池的特征是動態性,運行期間也可以將新的常量放入,如String.intern();

直接內存

此區域並不在JVM區域劃分範圍中,但這部分也可能會拋出OOM,NIO可以通過Native函數庫直接分配堆外內存並通過DirectByteBuffer對象對這塊內存進行操作,因為避免了數據在Native堆和Java堆之間的復制從而提高性能;

原文鏈接:https://my.oschina.net/u/580449/blog/2967037

JVM知識總結-運行時區域劃分