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