1. 程式人生 > 實用技巧 >JVM原理[總結筆記]

JVM原理[總結筆記]

1.JVM記憶體模型

2.堆

  • 堆GC:

    • Minor GC 新生代垃圾回收動作,使用複製演算法

    • Major GC/Full GC 老生代垃圾回收動作,使用標記清除演算法,耗時較長,程式會stop the world

    • 老生代記憶體不足會發生Full GC,如果回收後還是不足,則丟擲 java.lang.OutOfMemoryError: Java heap space

  • JVM管理的最大的一塊記憶體區域,存放著物件的例項,是執行緒共享區。

  • JAVA堆的分類:

    • JVM記憶體劃分為堆記憶體和非堆記憶體,堆記憶體分為年輕代(Young Generation)、老年代(Old Generation),預設比例為

      2:1,非堆記憶體就一個永久代(Permanent Generation)。

    • 年輕代又分為Eden和Survivor區。Survivor區由FromSpace和ToSpace組成。Eden區佔大容量,Survivor兩個區佔小容量,預設比例是8:1:1

  • 堆記憶體用途:存放的是物件,垃圾收集器就是收集這些物件,然後根據GC演算法回收。

  • 非堆記憶體用途:永久代,也稱為方法區,儲存程式執行時長期存活的物件,比如類的元資料、方法、常量、屬性等。

  • 在JDK1.8版本廢棄了永久代,替代的是元空間(MetaSpace),元空間與永久代上類似,都是方法區的實現,他們最大區別是:元空間並不在JVM中,而是使用本地記憶體。元空間有注意有兩個引數:

  • MetaspaceSize :初始化元空間大小,控制發生GC閾值

    • MaxMetaspaceSize : 限制元空間大小上限,防止異常佔用過多實體記憶體

    • 新生成的物件首先放到年輕代Eden區,當Eden空間滿了,觸發Minor GC,存活下來的物件移動到Survivor0區,Survivor0區滿後觸發執行Minor GC,Survivor0區存活物件移動到Suvivor1區,這樣保證了一段時間內總有一個survivor區為空。經過多次Minor GC仍然存活的物件移動到老年代。

    • 老年代儲存長期存活的物件,佔滿時會觸發Major GC=Full GC,GC期間會停止所有執行緒等待GC完成,所以對響應要求高的應用盡量減少發生Major GC,避免響應超時。Minor GC : 清理年輕代 Major GC : 清理老年代Full GC : 清理整個堆空間,包括年輕代和永久代,所有GC都會停止應用所有執行緒

3.程式計數器

  • 程式計數器(Program Counter Register)是JVM中一塊較小的記憶體區域,儲存著當前執行緒執行的虛擬機器位元組碼指令的記憶體地址(可以看作當前執行緒所執行的位元組碼的行號指示器)。

  • 如果執行緒執行的是java方法,這個計數器記錄的是正在執行的虛擬機器位元組碼指令的地址(可以理解為上圖所示的行號),如果正在執行的是native方法,這個計數器的值為undefined。

  • JVM的多執行緒是通過執行緒輪流切換並分配CPU執行時間片的方式來實現的,任何一個時刻,一個CPU都只會執行一條執行緒中的指令。為了保證執行緒切換後能恢復到正確的執行位置,每條執行緒都需要有一個獨立的程式計數器,各執行緒間的程式計數器獨立儲存,互不影響。

  • 此區域是唯一一個在java虛擬機器規範中沒有規定任何OutOfMemoryError情況的區域,因為程式計數器是由虛擬機器內部維護的,不需要開發者進行操作。

4.虛擬機器棧

  • 虛擬機器棧(Java Virtual Machine Stacks)是執行緒隔離的,每建立一個執行緒時就會對應建立一個Java棧,即每個執行緒都有自己獨立的虛擬機器棧。這個棧中又會對應包含多個棧幀,每呼叫一個方法時就會往棧中建立並壓入一個棧幀,棧幀儲存區域性變量表、操作棧、動態連結、方法出口等資訊,每一個方法從呼叫到最終返回結果的過程,就對應一個棧幀從入棧到出棧的過程。

  • 虛擬機器棧是一個後入先出的資料結構,執行緒執行過程中,只有處於棧頂的棧幀才是有效的,稱為當前棧幀,與這個棧幀相關聯的方法稱為當前方法,當前活動幀棧始終是虛擬機器棧的棧頂元素。

  • 區域性變量表存放了編譯期可知的各種基本資料型別和物件引用型別。通常我們所說的“棧記憶體”指的就是區域性變量表這一部分。

  • 區域性變量表所需的記憶體空間在編譯期間完成分配,當進入一個方法時,這個方法需要在幀分配多少記憶體是固定的,執行期間不會改變區域性變量表的大小。

  • 64位的long和double型別的資料會佔用2個區域性變數空間,其餘的資料型別只佔用1個

5.本地方法棧

  • 本地方法棧為Native 方法服務(虛擬機器棧為java方法服務)。
  • 虛擬機器規範中對本地方法棧中的方法使用的語言、使用方式與資料結構並沒有強制規定,因此具體的虛擬機器可以自由實現它

6.執行引擎

  • 負責解釋執行java位元組碼指令

7.JVM 常用引數

-Xms堆記憶體初始大小,單位m、g
-Xmx(MaxHeapSize) 堆記憶體最大允許大小,一般不要大於實體記憶體的80%
-XX:PermSize 非堆記憶體初始大小,一般應用設定初始化200m,最大1024m就夠了
-XX:MaxPermSize 非堆記憶體最大允許大小
-XX:NewSize(-Xns) 年輕代記憶體初始大小
-XX:MaxNewSize(-Xmn) 年輕代記憶體最大允許大小,也可以縮寫
-XX:SurvivorRatio=8 年輕代中Eden區與Survivor區的容量比例值,預設為8,即8:1
-Xss 執行緒堆疊記憶體大小,最小128k,jdk1.5以後預設為1M

8.一個調參demo

設定虛擬機器啟動記憶體為512M,最大使用記憶體為1024M,每個執行緒大小512K

java -Xmx1024m -Xms512m -Xss512k -jar 3d-cloud-app-server-0.0.1-SNAPSHOT.jar --http.port=7000 --server.port=7001