JVM——04執行時資料區(2)

如不來發表於2020-11-02

一、堆
 一個Java程式會建立一個JVM例項,一個JVM例項中會有一個堆和一個方法區,堆和方法區在該程式中的所有執行緒中是共享的。堆是Java記憶體管理的核心區域。
 Java堆區在JVM啟動的時候被建立,建立時其空間大小也就確定了(堆記憶體的大小在JVM啟動前是可以設定的),堆應該說是JVM管理的最大的一塊記憶體空間,也是GC執行垃圾回收的重點區域。
 《Java虛擬機器規範》規定,堆可以處於物理上不連續的記憶體空間中,但在邏輯上它應該被視為連續的。
 所有的執行緒共享堆,但是需要注意的是為了提高程式的併發性,在堆中還可以劃分執行緒私有的緩衝區(Thread Local Allocation Buffer,即TLAB),也就是說並非堆中的所有空間都是共享的。
 幾乎所有的物件例項以及陣列在執行時都分配在堆上(注意並不是所有的物件例項都會被分配在堆上),也就是說陣列和物件幾乎永遠不會儲存在棧上,棧幀中只是儲存物件的引用,這個引用指向物件或陣列在堆中的位置。在方法執行結束後,堆中的物件不會馬上被移除,而是在發生垃圾收集的時候才會被移除(以避免頻繁的發生GC,導致使用者執行緒卡頓)。
在這裡插入圖片描述
 1、堆空間的劃分
  現代垃圾收集器大部分都基於分代收集理論設計,堆空間的劃分在JDK8時做了一些改動,取消了永久區,增加了元空間(元空間實際上並不屬於堆)。
在這裡插入圖片描述
 2、堆空間大小的設定
  Java堆區用於儲存Java物件的例項,堆的大小在JVM啟動時就已經設定好了,可以通過“-Xmx”和“-Xms”來進行設定(通常會將這兩個值的大小設定為相同,其目的是為了能夠在Java垃圾回收機制清理完堆區後不需要重新計算堆區的大小,以提高效能)。
  -Xms:用於設定堆區的起始記憶體大小,等價於-XX:InitialHeapSize,預設大小是實體記憶體的1/64
  -Xmx:用於設定堆區的最大記憶體,等價於-XX:MaxHeapSize,預設大小是實體記憶體的1/4
  一旦堆區中的記憶體大小超過“-Xmx”所指定的最大記憶體時,將會丟擲OutOfMemoryError異常。
  在程式中可以獲取到這兩個值的大小:

// 單位轉換為m
long Xms = Runtime.getRuntime().totalMemory() / 1024 / 1024;
// 單位轉換為m
long Xmx = Runtime.getRuntime().maxMemory() / 1024 / 1024;

  :獲取到的值會比我們實際設定的或者預設的值略小,這是因為堆記憶體包含年輕代和年老代,但年輕代又分為一個Eden區和兩個Survive區,但兩個Survive區中只會有一個會被使用,因此在計算的時候只計算進去了一個Survive區。
 3、檢視堆空間大小設定
  有兩種方式可以檢視到堆空間大小的設定情況:
  ①使用JDK自帶的jps命令查詢出Java程式號,再使用JDK自帶的jstat -gc 程式號檢視
  ②在執行程式時加入VM執行引數-XX:+PrintGCDetails,把堆空間資訊列印到控制檯
在這裡插入圖片描述

相關文章