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