學習jvm,需要了解 類的加載機制、jvm內存結構、GC算法、GC調優。本文先談談JVM的內存結構。
JVM內存結構
記住一個JVM就是一個進程。
方法區又叫做持久代,不要把方法區和堆中的老年代、新生代等概念混淆,把方法區誤以為是堆的一部分。
JVM內存結構——堆(所有線程共享)
上面的圖有點複雜,簡單一點:
啟動一個虛擬機對應一個進程,線程共享進程所擁有的所有資源,java程序不管是主線程還是我們自己開啟的其他線程都共享虛擬機所擁有的資源——堆、方法區。
堆內存越大,Full GC會耗費更多的時間,但是越小,垃圾回收就會很頻繁,從而垃圾回收的總時間相對會更長,程序吞吐量會降低。
JVM內存結構——堆(所有線程共享)——老年代
JVM內存結構——堆(所有線程共享)——新生代
Eden(伊甸園空間) 倖存者From空間 倖存者To空間
下文中的N表示數值
JVM內存結構——堆(所有線程共享)——JVM參數設置(堆本身的大小,老年代新生代的大小、新生代伊甸園空間和倖存者空間的大小)
-Xms NNN 堆的最小值
-Xmx NNN 堆的最大值
-Xmn NNN 新生代的大小(等同於-XX:NewSize=NNN和-XX:MaxNewSize=NNN)
-XX:NewRatio=N 老年代和新生代的比例
沒有直接設置老年代大小的參數,不過可以通過該參數間接設置老年代的大小。-XX:NewRatio=4表示年老代與年輕代的比值為4:1。
當Xms=Xmx並設置了Xmn的情況下,該參數無需進行設置。
-XX:SurvivorRatio=N 新生代中eden(伊甸園)和survivior(倖存者,包括From和To)的比例
-XX:SurvivorRatio=8表示Eden區與Survivor區的大小比值是8:1:1,因為Survivor區有兩個。
-XX:TargetSurvivorRatio=N 新生代survivior空間可使用率,達到此值則把To空間的對象移動到老年代。
-XX:MaxTenuringThreshold=N 新生代中對象存活次數,即經過N次Minor GC之後依然存活的對象就會晉升到老年代。
JVM內存結構——方法區(所有線程共享,持久代)
-XX:PermSize=NNN:方法區初始內存的大小
-XX:MaxPermSize=NNN:方法區的最大內存
JVM內存結構——線程棧(包括Java棧、本地方法棧,線程私有)
-XssNNN:線程的棧大小。JDK5之後每個線程的棧大小默認為1M,相比之前的256K大了不少。物理內存不變情況下,該值越小能生成更多的線程越多。
JVM內存結構——程序計數器(線程私有)——大小
程序計數器(program counter register)佔用的內存空間小到可以忽略不計的。
JVM內存結構——程序計數器(線程私有)——作用
指示線程執行到字節碼文件(class)的哪一行。字節碼解釋器會通過改變計數器的值來獲取下一條要執行的字節碼指令,CPU某一時刻只會執行線程中的一條指令,當線程切換時,需要通過計數器來記錄目前執行到那一條指令。