JVM內(nèi)存模型###
描述主內(nèi)存和工作內(nèi)存之間的通信規(guī)則,避免數(shù)據(jù)不一致威鹿。所有線程共享JVM內(nèi)存區(qū)域main memory剃斧。而每個單獨線程又有自己的工作內(nèi)存。為了保證從工作內(nèi)存寫到主內(nèi)存的數(shù)據(jù)的一致性忽你,JVM定義了一系列的規(guī)則
- 所有變量都在主內(nèi)存中幼东,對所有線程共享(此處的變量與Java編程時所說的變量不一樣,指包括了實例字段科雳、靜態(tài)字段和構(gòu)成數(shù)組對象的元素根蟹,但是不包括局部變量與方法參數(shù),后者是線程私有的糟秘,不會被共享简逮。)
- 每條線程都有自己的工作內(nèi)存,保存主內(nèi)存中變量的拷貝尿赚,線程對變量的操作只能在工作內(nèi)存中完成
- 線程無法直接訪問對方的工作內(nèi)存
內(nèi)存之間的8個交互指令####
lock(main) unlock(main) read(main) load(work) use(work) assign(work) store(work) write(main)
必須順序執(zhí)行散庶,不必連續(xù)執(zhí)行
* 不許read load 和 store write單獨出現(xiàn)
* 不許丟棄assign結(jié)果蕉堰,必須同步回主內(nèi)存
* 不許未assign,直接同步主內(nèi)存
* 變量只能在主內(nèi)存誕生督赤。在使用use 和 store前嘁灯,必須先read和load
* 一個變量同一時刻只能由一個lock操作,與unlock必須成對出現(xiàn)
* 如果lock操作躲舌,那么這個變量需要重新執(zhí)行l(wèi)oad 和 assign操作
* 如果沒lock丑婿,不許unlock
* unlock前,必須執(zhí)行store和write
JVM內(nèi)存管理###
Java虛擬機在運行時會把它所管理的內(nèi)存分為若干不同個數(shù)據(jù)區(qū)域
主內(nèi)存: 方法區(qū)+堆, 由線程共享
工作內(nèi)存:棧 + 程序計數(shù)器没卸,線程私有
- 方法區(qū): 存放類信息羹奉,常量,靜態(tài)變量约计,即時編譯后的代碼诀拭。
- 堆:存放對象,細分為新生代(Eden煤蚌,F(xiàn)rom Survivor耕挨, To Survivor)+ 老年代, 也可以劃分出多個線程私有的分配緩存區(qū)TLAB
- 棧:局部變量表 + 操作數(shù)棧 + 動態(tài)鏈接 + 方法出參+其他(debug)
- 程序計數(shù)器:當前線程所執(zhí)行的代碼的行號指示器
JVM垃圾回收###
對象已死分析:引用計數(shù)法 Vs 可達性分析法
GC roots:棧中引用的對象,類靜態(tài)變量引用的對象尉桩,常量引用的對象筒占,本地方法JNI引用的對象
垃圾回收算法:復制,標記-整理蜘犁,標記-清除翰苫,分代回收
垃圾回收時間:安全點,安全區(qū)域
垃圾回收器:
新生代:serial parNew ParallelScavenge
老年代:serialOld parallelOld CMS
G1
CMS垃圾回收器:初始標記 -》 并發(fā)標記-》重新標記-》并發(fā)清除
JVM參數(shù)調(diào)優(yōu)###
標準參數(shù) (-) -verbose
非標準參數(shù) (-X) -Xmx20m
-Xmx 堆最大值
-Xms 堆最小值
-Xmn 新生代內(nèi)存
-Xss 棧內(nèi)存-
非穩(wěn)定參數(shù) (-XX) -XX:SurvivorRatio=8
行為參數(shù):
DisableExplicitGC 禁止顯示調(diào)用system.gc
UseConcMarkSweepGC
UseSearialGC
UseParallelGC性能調(diào)優(yōu):
PermSize 方法區(qū)內(nèi)存
MaxPermSize
SurvivorRatio 新生代中Eden和Survivor的容量比值这橙,默認8:1
PretenureSizeThreshold 直接晉升到老年代的對象大小閾值
MaxTenuringThreshold 晉升到老年代的年齡
UseAdaptiveSizePolicy 動態(tài)調(diào)整Java堆各區(qū)域的大小及進入老年代的年齡
HandlePromotionFailure 是否允許擔保失敗
ParallelGCThreads GC內(nèi)存回收的線程數(shù)
GCTimeRatio GC占總時間的比例奏窑,默認99, 只允許1%,只在parallelScavenge生效
MaxGCPauseMillis GC最大停頓時間屈扎,只在parallelScavenge生效
CMSInitiatingOccupancyFraction 老年代在空間占用多少后觸發(fā)回收埃唯,默認68%,只在CMS生效
UseCMSCompactionAtFullCollection 是否需要整理助隧,僅在CMS生效
CMSFullGCsBeforeCompaction 幾次后再整理
CompileThreshold JIT編譯閾值 client默認1500 server默認10000調(diào)試:
printGCDetails 打印內(nèi)存回收日志
HeapDumpOnOutOfMemoryError
TraceClassLoading
TraceClassUnloading
java工具###
jps: 打印java進程
jstack: 查看線程信息
jmap: 查看堆信息
jconsole筑凫, jinfo, jhat并村, javap, btrace
問題解決###
HeapOutOfMemory
當堆上分配的對象大于指定堆的最大值時滓技,拋出該錯哩牍。
可以使用-XX:+HeapDumpOnOutOfMemoryError 查看內(nèi)存快照進行分析
MethodArea OutOfMemory
方法區(qū)內(nèi)存不足,存放類信息令漂,常量膝昆,靜態(tài)變量丸边,即時編譯后的代碼,檢查這幾個信息是否有異常
大多的原因是因為動態(tài)產(chǎn)生過多的類荚孵。
ConstantPool OutOfMemory
常量池溢出妹窖,查看是否intern使用不當
DirectMemory OutOfMemory
本機直接內(nèi)存溢出,容量可通過-XX:MaxDirectMemorySize指定收叶,如果不指定骄呼,默認和堆最大值相同。
這個溢出發(fā)生在系統(tǒng)進行直接內(nèi)存分配判没。例如:unsafe.allocateMemory()
特征為:OOM后發(fā)現(xiàn)Dump問價你很小蜓萄,程序中直接或間接使用了NIO
Stack OutOfMemory
擴展棧時無法獲取足夠的內(nèi)存空間,在創(chuàng)建線程時
解決方法之一:減少最大堆
Stack OverFlow
棧深度大于虛擬機所允許的深度澄峰,經(jīng)常是由于死循環(huán)的遞歸調(diào)用
當一個Java程序響應很慢時如何查找問題