JVM系列(一)--JVM运行时数据区
隨著時間的推移,我覺得有必要將一些之前相對模糊但是對自身技術提高會有幫助的原理、概念、實現(xiàn)進行一下系統(tǒng)的整理,所以就從JVM系列開始吧。
本系列主要參考《Java虛擬機規(guī)范(第二版)》、周志明先生寫的《深入理解Java虛擬機》,具體虛擬機主要參照Hotspot。
一.Runtime Data Areas
在運營及維護我們的站點或者應用時,需要針對crash或者內(nèi)存溢出、內(nèi)存泄露定位問題以及調(diào)優(yōu)等工作,而Java這門語言或者是平臺提供了一個可以將內(nèi)存分配、回收屏蔽掉的JVM,所以我們非常有必要了解一下JVM的運行時數(shù)據(jù)分區(qū)情況。
圖1-Runtime Data Areas
從上圖可知,我們每創(chuàng)建一個Tread,JVM都會為該線程分配一個Program Counter Register、一個Java Virtual Machine Stack、一個Native Method Stack,以上三個區(qū)域都是線程私有,而Heap與Method Area是線程共享。
我們分別了解一下每個區(qū)域的作用、存儲的數(shù)據(jù)、線程私有\(zhòng)共享情況、可能出現(xiàn)的錯誤或異常。
1.Program Counter Register(程序計數(shù)器)
a.作用:被字節(jié)碼解釋器用來選取下一條需要執(zhí)行的字節(jié)碼指令。我們需要明確一點,Java虛擬機的多線程機制是通過線程輪流切換并分配處理器執(zhí)行時間的方式實現(xiàn)的,即在某一個特定的時刻,一個處理器只會執(zhí)行一條線程中的指令,從這個層面,該區(qū)域需要線程私有。
b.存儲的數(shù)據(jù):以當前線程正在被執(zhí)行的是Java方法還是Native方法。
(1).Java方法:本線程要被執(zhí)行的下一條字節(jié)碼指令地址。
(2).Native方法:空(Undefined)。
c.線程私有/共享情況:線程私有,每一個線程都持有一個程序計數(shù)器。
d.錯誤或異常:虛擬機規(guī)范中未規(guī)定該區(qū)域會拋出任何異常或錯誤。
2.Java Virtual Machine Stack(虛擬機棧)
a.作用:從名字上就可以猜測,這是一個Stack。該區(qū)域描述的是Java方法執(zhí)行的內(nèi)存模型:
每個Java方法執(zhí)行被執(zhí)行時都會常見一個棧幀(Stack Frame),該Stack Frame存儲了方法的局部變量表、操作棧、動態(tài)鏈接、方法出口等信息。每一個Java方法從被調(diào)用到執(zhí)行完成都對應著一個Stack Frame從進Stack到出Stack的過程。
b.存儲的數(shù)據(jù):本區(qū)域就是一個Stack結(jié)構(gòu),存儲的就是一個個被執(zhí)行的Stack Frame.
c.線程私有/共享情況:線程私有。
d.錯誤或異常:兩種異常(更精確的說是Error)
(1).StackOverflowError:請求深度超過JVM允許的深度時拋出,簡單點理解就是這個Stack滿了而已。
(2).OutOfMemoryError:無法申請到足夠的內(nèi)存時拋出。
4.Native Method Stack(本地方法棧)
這個區(qū)域的結(jié)構(gòu)及作用與虛擬機棧類似,只是這個區(qū)域描述的是Native方法執(zhí)行的內(nèi)存模型,所以HotSpot干脆把Java Virtual Machine Stack與Native Method Stack合并了。這個區(qū)域也是線程私有的,也會拋出StackOverflowError與OutOfMemoryError.
5.Java Heap(Java堆)
a.作用:存放對象實例(包括對象實例與數(shù)組)。
b.存儲的數(shù)據(jù):對象實例。
c.線程私有/共享情況:線程共享。
d.錯誤或異常:OutOfMemoryError.
該區(qū)域是垃圾收集器管理的主要區(qū)域,所以為了更快的分配內(nèi)存、更好的進行垃圾回收,Java Heap還可以進行細分:新生代與老年代。如果在細分的話有新生代又由Eden空間、From Survivor空間、To Survivor空間組成。
6.Method Area(方法區(qū))
a.作用:存儲被虛擬機加載的類信息、常量、靜態(tài)變量、JIT編譯后的代碼。
b.存儲的數(shù)據(jù):同上
c.線程私有/共享情況:線程共享
d.錯誤或異常:OutOfMemoryError.
7.Runtime Constant Pool(運行時常量池)
a.作用:存儲編譯期生成的各種字面量和符號引用
b.存儲的數(shù)據(jù):同上
c.線程私有/共享情況:線程共享
d.錯誤或異常:OutOfMemoryError.
該區(qū)域是Method Area的一部分。
二.Some Options
JVM Options:
| 參數(shù)名 | 含義 | 默認值 | 說明 |
| -Xms | Java Heap初始大小 | 物理內(nèi)存的1/64,但是小于1GB | |
| -Xmx | Java Heap最大值 | 物理內(nèi)存的1/4,但是小于1GB | |
| -Xmn | 新生代大小 | 該區(qū)域由Eden空間、From Survivor空間、To Survivor空間組成 | |
| PermSize | 方法區(qū)初始大小 | 物理內(nèi)存的1/64 | |
| MaxPermSize | 方法區(qū)的最大值 | 物理內(nèi)存的1/4 | |
| -Xss | JVM Stack大小 | JDK5.0之前默認256K,之后默認1M. 在物理內(nèi)存不變的情況下,可以通過減小該值來獲取更大的線程創(chuàng)建數(shù)量。 | |
| NewRatio | 新生代與老年代的比值 | 如果-XX:NewRatio=4表示新生代與老年代的比值為1/4 | |
| SurvivorRatio | Eden空間與Survivor空間的比值 | ||
| LargePageSizeInBytes | 內(nèi)存頁的大小 | 用法-XX:LargePageSizeInBytes=128m | |
| UseFastAccessorMethods | 原始類型的快速優(yōu)化 | ||
| DisableExplicitGC | 忽略來自System.gc()方法觸發(fā)的垃圾收集 | 默認關閉 | |
Help Options
| -XX:+PrintGC | 輸出形式: [GC 118250K->113543K(130112K), 0.0094143 secs] | ||
| -XX:+PrintGCDetails | 輸出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] | ||
| -XX:+PrintGCTimeStamps | |||
| -XX:+PrintGC:PrintGCTimeStamps | 可與-XX:+PrintGC -XX:+PrintGCDetails混合使用 輸出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs] | ||
| -XX:+PrintGCApplicationStoppedTime | 打印垃圾回收期間程序暫停的時間.可與上面混合使用 | 輸出形式:Total time for which application threads were stopped: 0.0468229 seconds | |
| -XX:+PrintGCApplicationConcurrentTime | 打印每次垃圾回收前,程序未中斷的執(zhí)行時間.可與上面混合使用 | 輸出形式:Application time: 0.5291524 seconds | |
| -XX:+PrintHeapAtGC | 打印GC前后的詳細堆棧信息 | ||
| -Xloggc:filename | 把相關日志信息記錄到文件以便分析. 與上面幾個配合使用 | ||
-XX:+PrintClassHistogram | garbage collects before printing the histogram. | ||
| -XX:+PrintTLAB | 查看TLAB空間的使用情況 | ||
| XX:+PrintTenuringDistribution | 查看每次minor GC后新的存活周期的閾值 | Desired survivor size 1048576 bytes, new threshold 7 (max 15) |
轉(zhuǎn)載于:https://blog.51cto.com/paladinapple/1317874
總結(jié)
以上是生活随笔為你收集整理的JVM系列(一)--JVM运行时数据区的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop Mapreduce分区、分
- 下一篇: [转]localCache与集中式cac