(1)程序計數器
看作當前線程所執行的字節碼行號顯示器;任意時刻,一個CPU都會執行一條線程中的指令,爲了線程切換後能回到正確位置,每一個線程都須要一個獨立的線程計數器;執行native方法時,計數器值爲空;此區域沒有任何OutOfMemoryError的區域;html
(2)虛擬機棧
虛擬機棧的生命週期和線程同步,虛擬機棧中的局部變量表用於存儲各類基本數據類型、對象引用類型;long和double會佔用兩個局部變量表的空間,局部變量表在編譯器完成空間分配;
StackOverflowError:線程請求過多
OutOfMemoryError:若是虛擬機棧擴展時沒法申請到足夠內存;java
(3)本地方法棧
與虛擬機棧發揮的做用很是類似,區別是:虛擬機棧爲Java方法服務的;本地方法棧是爲native方法服務的;算法
(4)Java堆
存放實例對象的以及數組的;
OutOfMemoryError異常;數組
堆內存劃分:tomcat
Young Generation:新生代
全部新生成的對象首先都是放在年輕代的。年輕代的目標就是儘量快速的收集掉那些生命週期短的對象。年輕代分三個區:一個Eden ['i:dən]區,兩個 Survivor[sə'vaɪvə]區(通常而言)。大部分對象在Eden區中生成。當Eden區滿時,還存活的對象將被複制到Survivor[sə'vaɪvə]區(兩個中的一個),當這個 Survivor區滿時,此區的存活對象將被複制到另一個Survivor區,當這個Survivor去也滿了的時候,從第一個Survivor區複製過來的而且此時還存活的對象,將被複制年老區。多線程
Old Generation:老年代
在年輕代中經歷了N次垃圾回收後仍然存活的對象,就會被放到年老代中。所以,能夠認爲年老代中存放的都是一些生命週期較長的對象。併發
Perm Area:永久帶
用於存放靜態文件,現在Java類、方法等。jvm
(5)方法區
虛擬機加載的類信息,常量,靜態變量等;
運行時常量池也是方法區的一部分:存放編譯器生成的各類字面量和符號引用;
OutOfMemoryError異常;佈局
(1)虛擬機執行new指令 ----> 檢查指令參數是否能在常量池中定位到類的符號引用 ----> 若是沒有檢查到引用表明的類,則先執行類的加載過程 ----> 類加載經過後,爲新生對象分配內存 ----> 分配到的內存空間初始化爲零 ----> 虛擬機對對象進行設置 ----> 執行init方法,完成對象建立
(2)對象在內存中存儲佈局可分爲3塊區域:
對象頭:一部分存儲對象自身運行時數據,如hashCode,線程持有的鎖等;一部分是類型指針,肯定對象是哪一個類的實例;
實例數據:就是程序代碼中定義的各類類型字段內容;
對齊填充:沒有特殊含義,僅僅起到佔位符的做用;ui
Java語言中可做爲GC roots的對象有:
虛擬機棧引用的對象,方法區中類的靜態屬性、常量引用的對象,本地方法區中Native方法引用的對象;
(1)標記-清除算法:
首先標記處全部須要回收的對象,標記完成後統一回收;執行下圖所示:
主要有兩個缺點:一是執行效率不高,另外一個是會產生大量不連續的內存碎片,致使再次分配較大對象時,沒法獲得連續的內存空間而再一次觸發垃圾回收機制;
(2)複製算法:
爲了解決標記-清除算法的效率問題,可使用複製算法;它將內存劃分爲大小相等的兩塊,每次使用其中一塊,當一塊內存使用完了,就將存活的對象複製到另外一塊,而後回收已使用過的內存;
該算法在對象存活較多時,效率底下,同時內存空間浪費;適合於新生代內存;
(3)標記-整理算法:
標記全部可回收對象,它不是直接對可回收對象進行清理;而是讓全部的存活對象都向一端移動,而後直接清理掉端邊界之外的內存;
(4)分代收集算法:
目前商業虛擬機都採用分代收集算法。
Serial ['sɪərɪəl]
收集器ParNew [pɑː][njuː]
收集器Serial Old
收集器Parallel Old ['pærəlel]
收集器其實每一個垃圾回收器的日誌是不同的,可是爲了方便查看日誌它們也有必定的共性,以下所示的一段 GC 日誌:
33.125: [GC [DefNew: 3324k->152k(3712k),0.0025925 secs] 3324->152k(11904k),0.003168 secs] 100.667: [Full GG [Tenurend: 0k->210k(1024k),0.00149142 secs]4603k->210k(19456k), [Perm : 2999k->2999k(21248k)],0.0150007 secs] [Times:user=0.01 sys=0.00,real=0.02 secs]
Serial
收集器,它的新生代命名爲Default New Generation
,因此顯示"[DefNew"3324k->152k(3712k)
表示"GC前該區域已使用容量->GC後該內存區域已使用容量(該內存區域總容量)"3324->152k(11904k)
表示"GC前Java堆已使用容量->GC後Java堆已使用容量(Java堆總容量)"作GC調優須要大量的實踐,耐心和對項目的分析。作GC的調優很大程度上依賴於對系統的分析,系統擁有怎樣的對象以及他們的平均生命週期。舉個例子,若是一個應用大可能是短生命週期的對象,那麼應該確保Eden區足夠大,這樣能夠減小Minor GC的次數。能夠經過-XX:NewRatio來控制新生代和老年代的比例,好比-XX:NewRatio=3表明新生代和老年代的比例爲1:3。須要注意的是,擴大新生代的大小會減小老年代的大小,這會致使Major GC執行的更頻繁,而Major GC可能會形成用戶線程的停頓從而下降系統吞吐量。JVM中能夠用NewSize和MaxNewSize參數來指定新生代內存最小和最大值,若是兩個參數值同樣,那麼就至關於固定了新生代的大小。
(1)Minor ['maɪnə] GC:從年輕代空間(包括 Eden 和 Survivor 區域)回收內存被稱爲 Minor GC;
(2)Major['meɪdʒə] GC:是清理老年代;
(3)Full GC:是清理堆空間,包括年輕代和老年代;
參考文章:Minor GC,Major GC,Full Gc
(1) -Xms : 堆內存的初始大小,默認是物理內存的1/64
(2) -Xmx : 堆內存的最大值,默認不超過物理內存
(3) -Xmn : 年輕代堆內存大小
(4) -Xss : 棧內存大小設置
(5) -XX:PermSize : 內存永久區的初始大小
(6) -XX:MaxPermSize : 內存永久區的大小
(7) -XX:SurvivorRatio : Eden區與Survivor區的大小比值;設置成8,則兩個Survivor區與一個Eden區的比值是2:8
(8) -XX:+UseAdaptiveSizePolicy : 動態調整 Java 堆內存中各個區域的大小以及即進入老年代的年齡
(1) -XX:UseParallelGC : 使用 Parallel Scavenge(年輕代並行的多線程收集器) + Serial Old(老年代單線程收集器) 收集器
(2) -XX:UseParNewGC : 使用 ParNew + Serial Old 收集器
(3) -XX:ParallelGCThreads : 並行收集的線程數
(4) -XX:UseParallelOldGC : 使用 Parallel Scavenge(年輕代並行的多線程收集器) + Parallel Old 收集器
(5) -XX:MaxGCPauseMillis : 設置GC的最大停頓時間,僅在使用 Parallel Scavenge 收集器時生效
(6) -XX:+UseConcMarkSweepGC : 使用 ParNew + CMS + Serial Old 組合收集器
(7) -XX:GCTimeRatio : GC時間佔總時間的比例,默認99,即容許 1% 的GC時間。僅在使用 Parallel Scavenge 收集器時生效
(1) -XX:+DisableExplicitGC : 忽略來自程序中System.gc()方法觸發的垃圾回收
(2) -XX:+PrintGCDetails : 打印GC的相信信息
(3) -XX:+PrintHeapAtGC :
(4) -XX:+PrintTenuringDistribution :
(5) -XX:+PrintGCTimeStamps : 打印GC停頓耗時
(6) -XX:+PrintGCDateStamps :
(7) -XX:+HeapDumpOnOutOfMemoryError :
(8) -XX:ErrorFile :
(9) -XX:HeapDumpPath :
-XX:CMSFullGCsBeforeCompaction=0 : cms 收集器每次進入Full GC都進行碎片整理
-XX:+UseCMSCompactAtFullCollection
-XX:CMSInitiatingOccupancyFraction=80 : cms 收集器觸發比例(當空間使用了80%後就觸發回收)
-XX:ReservedCodeCacheSize=128m :
-XX:InitialCodeCacheSize=128m
/export/servers/jdk1.6.0_25/bin/java -server
-Xms128M -Xmx256M -Xss256K
-XX:PermSize=32M
-XX:MaxPermSize=32M
-XX:+UseAdaptiveSizePolicy
-XX:+UseParallelGC
-XX:+UseParallelOldGC
-XX:GCTimeRatio=39
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps -Xloggc:/export/home/tomcat/logs/loghub.360buy.com/jcollector/gc.log
-XX:+HeapDumpOnOutOfMemoryError
-XX:ErrorFile=/export/home/tomcat/logs/loghub.360buy.com/jcollector/hs_err.log
-XX:HeapDumpPath=/export/home/tomcat/logs/loghub.360buy.com/jcollector/heap_dump.hprof -classpath
JVM_ARGS="-server -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.io.tmpdir=/tmp -Djava.net.preferIPv6Addresses=false"
JVM_GC="
-XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+UseConcMarkSweepGC -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps
"
JVM_GC=$JVM_GC"
-XX:CMSFullGCsBeforeCompaction=0 -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=80 "
JVM_HEAP="
-XX:SurvivorRatio=8 -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:ReservedCodeCacheSize=128m -XX:InitialCodeCacheSize=128m "
JVM_SIZE="-Xmx4g -Xms4g -Xmn1g"