1 JVM內(nèi)存結(jié)構(gòu)
JVM內(nèi)存結(jié)構(gòu)主要包括:Heap(堆)、Stack(堆棧)和Method Area(方法區(qū)、非堆)等
JDK8取消了方法區(qū)的永久代PermGen,新增了元空間Metaspace,Metaspace與PermGen之間最大的區(qū)別在于:Metaspace并不在虛擬機中,而是使用本地內(nèi)存。
1.1 Heap(堆):年輕代、老年代
? ? ? ? 年輕代:伊甸園、兩個幸存者區(qū)(from、to)
? ? ? ? 堆的GC過程:當伊甸園、幸存者區(qū)滿足GC條件時候,會執(zhí)行Young GC
? ? ? ? ? ? Young GC:Minor GC,復制算法(兩個幸存者區(qū)之間復制)
? ? ? ? ? ? ? ? 伊甸園存活對象復制到幸存者區(qū)(to)
? ? ? ? ? ? ? ? 判斷幸存者區(qū)(from)中存活對象的年齡閥值
? ? ? ? ? ? ? ? ? ? 如果年齡到閥值則會進入老年代
? ? ? ? ? ? ? ? ? ? 未到閥值則也復制到幸存者區(qū)(to),并且年齡加1
? ? ? ? ? ? ? ? 如果幸存者區(qū)(to)已滿則全部進入老年代
? ? ? ? ? ? ? ? 如果老年代已滿除法Old GC
? ? ? ? ? ? ? ? 幸存者區(qū)from和to角色交換,保證to區(qū)為空
? ? ? ? ? ? Old GC: Full GC,標記-整理算法,標記出存活對象(存在引用的對象)
1.2 Stack(堆棧):存放對象的引用、每個運行線程的線程棧、每個方法的棧幀
1.3 JVM常用參數(shù)
-Xms和-Xmx
? ? -Xms4g -Xmx4g
? ? 用于設(shè)置堆的最小和最大值,一般兩個值設(shè)置一樣大(否則GC后計算堆區(qū)會降低JVM效率)
-Xmn
? ? -Xmn2g
? ? 用于設(shè)置年輕代大小,配置了這個則不需要配置-XX:NewSize和-XX:MaxNewSize
-Xss
? ? -Xss512k
? ? 用于設(shè)置單個線程的堆棧大小,JDK5.0以后每個線程堆棧大小為1M
-XX:NewSize和-XX:MaxNewSize
? ? 用于設(shè)置年輕代的大小,一般兩個值設(shè)置一樣大,建議采用-Xmn,建議設(shè)為整個堆大小的1/3或者1/4。
-XX:SurvivorRatio
? ? -XX:SurvivorRatio=4
? ? 用于設(shè)置伊甸園和其中一個幸存者區(qū)的比值,
? ? ? ? 為4則說明兩個幸存者區(qū)和伊甸園比值為2:4,即一個幸存者區(qū)占年輕代1/6
? ? ? ? 為5則說明兩個幸存者區(qū)和伊甸園比值為2:5,即一個幸存者區(qū)占年輕代1/7
2 Java內(nèi)存模型(JMM)
Java內(nèi)存模型主要分為主內(nèi)存和工作內(nèi)存,工作內(nèi)存包含了主內(nèi)存的變量拷貝,線程對變量的讀寫操作都在工作內(nèi)存中執(zhí)行,執(zhí)行完成后會同步至主內(nèi)存。
JMM主要圍繞并發(fā)編程中的原子性、可見性、有序性三個特征建立的
原子性:(synchronized)一個操作要么都執(zhí)行,要么都不執(zhí)行
可見性:(synchronized、volatile)一個線程對共享變量做了修改之后,其他線程能立即看到這個變量的變化
有序性:(synchronized、volatile)禁止指令重排
volatile修飾的變量每次操作都會先從主內(nèi)存同步,然后再執(zhí)行變量操作
JMM和JVM沒有關(guān)系,勉強對應(yīng)起來主內(nèi)存對應(yīng)JVM中Heap(堆)的對象實例數(shù)據(jù)部分,工作內(nèi)存對應(yīng)JVM中Stack(堆棧)的部分區(qū)域
3 Java對象模型
對象的實例數(shù)據(jù)存儲在Heap(堆)中,對象引用存儲在棧中,對象元數(shù)據(jù)存儲在元空間(JDK8以前在方法區(qū))中