1. 程式人生 > >java虛擬機器執行時記憶體區域

java虛擬機器執行時記憶體區域

java虛擬機器執行時記憶體區域

程式計數器、Java虛擬機器棧、本地方法棧、Java堆、方法區 (前3個為執行緒私有,後2個為執行緒共享)


(1)程式計數器

當前執行緒所執行的位元組碼的行號指示器;通過改變這個計數器的值來選取下一條需要執行的位元組碼指令;分支、迴圈、跳轉、異常處理、執行緒恢復等功能依賴其完成;執行緒切換後能恢復到正確的執行位置,故每個執行緒需要一個獨立的程式計數器,即“執行緒私有“

(2)Java虛擬機器棧

  • Java Virtual Machine Stacks; 也就是通常所說的“棧”;執行緒私有;
  • 存在資料結構–棧幀(Stack Frame),用於儲存區域性變量表、運算元棧、方法出口等;區域性變量表中存放了編譯期可知
    的基本資料型別(boolean,int…)、物件引用(reference,可以理解為指向物件起始位置的引用指標,或者代表物件的控制代碼)
  • 存在兩種異常: 1)StackOverflowError(棧溢位): 請求棧深度大於虛擬機器棧深度 2)OutOfMemoryError(OOM): 動態擴充套件記憶體時,無法申請到足夠的記憶體

(3)本地方法棧

與虛擬機器棧作用類似;虛擬機器棧為虛擬機器執行Java方法服務,本地方法棧為虛擬機器使用到底Native方法服務; 也會丟擲StackOverflowError和OutOfMemoryError異常

(4)Java堆

  • Java Heap;所有執行緒共享的一塊記憶體區域;唯一目的:存放物件例項(物件例項和陣列);
  • java堆是垃圾收集器管理的主要區域;一般採用分代收集演算法;細分為:新生代和老年代,再細緻點有Eden空間、From Survivor空間、To Survivor空間等;某些情況下,Java堆坑可能劃分出多個執行緒私有的分配緩衝區(TLAB);
  • 可以通過-Xmx和-Xms控制堆大小;當堆記憶體無法擴充套件時,會丟擲OOM

(5)方法區

  • 執行緒共享的記憶體區域;用於儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料;在HotSpot虛擬機器中稱為“永久代”
  • __執行時常量池__是方法區的一部分, 用於存放編譯器生成的各種字面量和符號引用;執行時也可能將新的常量放入池中,例如String的intern()方法
  • jdk8取消了永久代,儲存在永久代的部分資料就已經轉移到Java Heap或者Native memory,符號引用(Symbols)轉移到了native memory;字串常量池(interned strings)轉移到了Java heap;類的靜態變數(class statics)轉移到了Java heap;方法存放於元空間(Metaspace)

注:直接記憶體(Direct Memory):不是虛擬機器中的記憶體區域;NIO中基於通道(Channel)和緩衝區(Buffer)的IO方式,可以使用Native函式庫分配對外記憶體,然後通過DirectByteBuffer作為引用對其操作,不會收到堆大小的限制。