JVM调优系列:(二)JVM运行时数据区域
1) Method Area
2) Heap
3) Java Stacks
4) PC Registers
5) Native Method Stacks
?
JAVA的JVM的內(nèi)存模型大致可分為3個區(qū):
堆區(qū):
1.存儲的全部是對象,每個對象都包含一個與之對應(yīng)的class的信息。(class的目的是得到操作指令)
2.jvm只有一個堆區(qū)(heap)被所有線程共享,堆中不存放基本類型和對象引用,只存放對象本身
棧區(qū):
線程在執(zhí)行一個Java方法時候,它的PC寄存器總是指向下一條需要執(zhí)行的指令, 而它的Java棧則保存線程中Java方法的調(diào)用狀態(tài),比如: 它的局部變量、傳入方法的參數(shù)、返回值、以及運算的中間結(jié)果等。
1.每個線程包含一個棧區(qū),棧中只保存基礎(chǔ)數(shù)據(jù)類型的對象和自定義對象的引用(不是對象),對象都存放在堆區(qū)中
2.每個棧中的數(shù)據(jù)(原始類型和對象引用)都是私有的,其他棧不能訪問。
?
本地方法棧:
當(dāng)某個線程調(diào)用一個本地方法時,它就進入了一個全新的并且不再受虛擬機限制的本地方法棧。本地方法可以通過本地方法接口來訪問虛擬機的運行時數(shù)據(jù)區(qū),它和虛擬機擁有同樣的權(quán)限(能力)。
任何本地方法接口都會使用某種本地方法棧。當(dāng)線程調(diào)用Java方法時,虛擬機會創(chuàng)建一個新的棧幀并壓入Java棧。然而當(dāng)它調(diào)用的是本地方法時,虛擬機會保持Java棧不變,不再在線程的Java棧中壓入新的幀,虛擬機只是簡單地動態(tài)鏈接并直接調(diào)用指定的本地方法。
如果某個虛擬機實現(xiàn)的本地方法接口是使用C連接模型的話,那么它的本地方法棧就是C棧。當(dāng)C程序調(diào)用一個C函數(shù)時,其棧操作都是確定的。傳遞給該函數(shù)的參數(shù)以某個確定的順序壓入棧,它的返回值也以確定的方式傳回調(diào)用者。
?
方法區(qū):
1.又叫靜態(tài)區(qū),跟堆一樣,被所有的線程共享。方法區(qū)包含所有的class和static變量。
2.方法區(qū)中包含的都是在整個程序中永遠(yuǎn)唯一的元素,如類型的基本信息, 常量池, 字段信息, 方法信息, 靜態(tài)變量, ClassLoader的引用等變量。?
?
??Perm
Perm代主要保存classs,method,filed對象,這部門的空間一般不會溢出,除非一次性加載了很多的類,不過在涉及到熱部署的應(yīng)用服務(wù)器的時候,有時候會遇到j(luò)ava.lang.OutOfMemoryError?:?PermGen?space?的錯誤,造成這個錯誤的很大原因就有可能是每次都重新部署,但是重新部署后,類的class沒有被卸載掉,這樣就造成了大量的class對象保存在了perm中。
??Tenured
Tenured區(qū)主要保存生命周期長的對象,一般是一些老的對象,當(dāng)一些對象在Young復(fù)制轉(zhuǎn)移一定的次數(shù)以后,對象就會被轉(zhuǎn)移到Tenured區(qū),一般如果系統(tǒng)中用了application級別的緩存,緩存中的對象往往會被轉(zhuǎn)移到這一區(qū)間。
??Young
Young區(qū)被劃分為三部分,Eden區(qū)和兩個大小嚴(yán)格相同的Survivor區(qū),其中Survivor區(qū)間中,某一時刻只有其中一個是被使用的,另外一個留做垃圾收集時復(fù)制對象用,在Young區(qū)間變滿的時候,minor?GC就會將存活的對象移到空閑的Survivor區(qū)間中,根據(jù)JVM的策略,在經(jīng)過幾次垃圾收集后,任然存活于Survivor的對象將被移動到Tenured區(qū)間。
?
標(biāo)準(zhǔn)參數(shù)-,所有的JVM實現(xiàn)都必須實現(xiàn)這些參數(shù)的功能,而且向后兼容,-client
非標(biāo)準(zhǔn)參數(shù)-X ,默認(rèn)JVM實現(xiàn)此功能,但是不保證所有JVM都實行,而且不保證向后兼容,-Xmxn
非穩(wěn)定參數(shù)-XX,此類參數(shù)各個JVM的實現(xiàn)會有不同,而且隨時可能消失,+XX:-UseParallelGC
?
-Xmx3550m:設(shè)置JVM最大可用內(nèi)存為3550M。默認(rèn)是物理內(nèi)存的1/4但小于1G。
-XX:MinHeapFreeRatio=40:修改垃圾回收之后堆中可用內(nèi)存的最小百分比,缺省值是40。如果垃圾回收后至少還有40%的堆內(nèi)存沒有被釋放,則系統(tǒng)將增加堆的尺寸。-Xms、-Xmx相等時無效.
-XX:MaxHeapFreeRatio=70:?改變垃圾回收之后和堆內(nèi)存縮小之前可用堆內(nèi)存的最大百分比,缺省值為70。這意味著如果在垃圾回收之后還有大于70%的堆內(nèi)存,則系統(tǒng)就會減少堆的尺寸。-Xms、-Xmx相等時無效.
-Xms3550m:設(shè)置JVM初始內(nèi)存為3550m。此值可以設(shè)置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內(nèi)存。默認(rèn)是物理內(nèi)存的1/64但小于1G。-Xmx -Xms之差就是Virtual空間的大小。
-Xmn2g:設(shè)置年輕代大小為2G。整個JVM內(nèi)存大小=年輕代大小 + 年老代大小 + 持久代大小。持久代一般固定大小為64m,所以增大年輕代后,將會減小年老代大小。此值對系統(tǒng)性能影響較大,Sun官方推薦配置為整個堆的3/8。
-Xss128k:設(shè)置每個線程的堆棧大小。JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。更具應(yīng)用的線程所需內(nèi)存大小進行調(diào)整。
-XX:NewRatio=4:設(shè)置年輕代(包括Eden和兩個Survivor區(qū))與年老代的比值(除去持久代)。設(shè)置為4,則年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5
-XX:SurvivorRatio=4:設(shè)置年輕代中Eden區(qū)與Survivor區(qū)的大小比值。設(shè)置為4,則兩個Survivor區(qū)與一個Eden區(qū)的比值為2:4,一個Survivor區(qū)占整個年輕代的1/6, 默認(rèn)是32.
-XX:PermSize=16M-XX:MaxPermSize=16M:?設(shè)置持久代大小為16m。
-XX:PretenureSizeThreshold=3m:對象超過多大是直接在舊生代分配,新生代采用Parallel Scavenge GC時無效.
-XX:LargePageSizeInBytes=128M:Javaheap的分頁頁面大小, 默認(rèn)4m
-XX:TLABWasteTargetPercent:JVM所占用的主要內(nèi)存都是從堆空間分配的,堆是所有線程共享的,因此在堆上分配內(nèi)存需要加鎖,Sun JDK為提升效率,會為每個新建的線程在Eden上分配一塊獨立的空間由該線程獨享,這塊空間稱為TLAB(Thread Local Allocation Buffer)。其大小由JVM根據(jù)運行情況計算得到,也可通過參數(shù)-XX:TLABWasteTargetPercent來設(shè)置TLAB可占用的Eden空間的百分比,默認(rèn)值為1%。在TLAB上分配內(nèi)存不需要加鎖,因此JVM在給線程中的對象分配內(nèi)存時會盡量在TLAB上分配。如果對象過大或TLAB用完,則仍然在堆上進行分配。
-XX:MaxTenuringThreshold=0:設(shè)置垃圾最大年齡。如果設(shè)置為0的話,則年輕代對象不經(jīng)過Survivor區(qū),直接進入年老代。對于年老代比較多的應(yīng)用,可以提高效率。默認(rèn)值是32, 在linux64的java6下默認(rèn)值是15, 對于并行收集器無效.
?
-XX:+DoEscapeAnalysis開啟了逸出分析,某些情況所有性能有了很大的提高
-XX:+AggressiveOpts加快編譯,jdk5U6引入, JDK6默認(rèn)啟用.
-XX:+UseBiasedLocking?鎖機制的性能改善.
-XX:SoftRefLRUPolicyMSPerMB?每兆堆空閑空間中SoftReference的存活時間.
-XX:+UseFastAccessorMethods原始類型get,set方法的優(yōu)化.
-XX:+DisableExplicitGC禁止java程序中的System.gc()的調(diào)用.
-XX:+UseCompressedOops?壓縮指針,起到節(jié)約內(nèi)存占用的新參數(shù),JDK1.6u14開始
-XX:CompileThreshold當(dāng)某個方法被調(diào)用+循環(huán)次數(shù)累計超過該值時,觸發(fā)標(biāo)準(zhǔn)的JIT編譯,默認(rèn)CompileThreshold=?10000;
-XX:InterpreterBackwardBranchLimit當(dāng)某個方法調(diào)用+循環(huán)次數(shù)累計超過該值時,觸發(fā)OSR形式的JIT編譯,10070
-XX:+PrintEscapeAnalysis打印逃逸分析
-XX:+PrintAssembly?打印JIT編譯器變成x86指令
總結(jié)
以上是生活随笔為你收集整理的JVM调优系列:(二)JVM运行时数据区域的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从缓存行出发理解volatile变量、伪
- 下一篇: JVM调优系列:(三)类加载和执行机制