Java JVM总结
一、jvm參數(shù)
1)內(nèi)存
-Xms
-Xmx
-Xss
-Xloggc:file
-Xprof
-XX:+DisabledExplicitGC
-XX:PreBlockSpin
-XX:CompileThreshold
2)Parallel
-XX:SurvivorRatio
-XX:PreTenureSizeThreshold
-XX:MaxTenuringThreshold
-XX:+ParallelGCThreads
-XX:+UseAdaptiveSizePolicy
3)CMS
-XX:+UseConcMarkSweepGC
-XX:MaxTenuringThreshold
-XX:ParallelCMSThreads
-XX:CMSInitiatingOccupancyFraction
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction
-XX:+CMSClassUnloadingEnabled
-XX:CMSInitiatingPermOccupancyFraction
-XX:GCTimeRatio
-XX:MaxGCPauseMillis
4)G1
-XX:+UseG1GC
-XX:MaxGCPauseMillis
-XX:GCPauseIntervalMillis
-XX:+G1HeapRegionSize
-XX:G1NewSizePercent
-XX:G1MaxNewSizePercent
-XX:GCTimeRatio
-XX:ConcGCThreads
-XX:InitiatingHeapOccupancyPercent
二、內(nèi)存模型
(1)運行時數(shù)據(jù)區(qū)
程序計數(shù)器
Java 虛擬機棧
本地方法棧
Java 堆
方法區(qū)
(2)對象內(nèi)存分配
1)內(nèi)存分配方式
指針碰撞、空閑列表
2)內(nèi)存分配策略
優(yōu)先在 Eden 區(qū)分配、大對象直接進入老年代、長期存活對象將進入老年代
3)內(nèi)存分配空間
1.棧分配
技術(shù):逃逸分析、標(biāo)量替換
缺點:無法棧上分配共享的對象?
2.TLAB
優(yōu)點:盡量避免從堆上直接分配內(nèi)存從而避免頻繁的鎖爭用
缺點:有內(nèi)存孔隙問題,影響 gc 掃描性能?
3.Eden
4.年老代
4)內(nèi)存分配并發(fā)安全問題
同步處理(采用 CAS + 失敗重試)
TLAB 上分配
5)對象的創(chuàng)建方式
new、Class.newInstance、Constructor.newInstance、clone、反序列化
6)對象的訪問定位
句柄?、直接指針(HotSpot)
7)引用類型
強引用、軟引用、弱引用、虛引用(幽靈引用/幻影引用)PhantomReference?
8)對象拷貝克隆
深拷貝和淺拷貝
拷貝有兩種方式:
實現(xiàn) Cloneable 接口并重寫 Object 類中的 clone()方法;
實現(xiàn) Serializable 接口,通過對象的序列化和反序列化實現(xiàn)克隆,可以實現(xiàn)真
正的深度克隆
9)內(nèi)存使用
1.內(nèi)存溢出
OOM錯誤:stackoverflow錯誤,permgen space錯誤
2.內(nèi)存泄漏
類的靜態(tài)變量
各種連接,如數(shù)據(jù)庫連接、網(wǎng)絡(luò)連接和IO連接等
變量不合理的作用域
內(nèi)部類持有外部類
改變哈希值
單例模式
監(jiān)聽器
ThreadLocal的誤用
三、GC
(1)判斷垃圾
1)算法
引用計數(shù)(缺點:不能解決循環(huán)引用)、根可達性分析
2)GC roots
1.虛擬機棧(JVM stack)中引用的對象
2.方法區(qū)中類靜態(tài)屬性引用的對象
3.本地方法棧(Native Stack)引用的對象
(2)垃圾回收算法
復(fù)制、標(biāo)記清除、標(biāo)記整理、分代回收、分塊回收
(3)hopspot垃圾回收器
1)GC類型
Minor GC
Major GC
Full GC(Major GC對老年代/永久代的stop the world的GC)
Mixed GC(G1)
1)新生代回收器
serial、parNew、parallelScavenge
2)老年代回收器
CMS、serialOld、parallelOld?
3)整堆回收器
G1
關(guān)系:(serial和parNew)搭配(CMS和serialOld)、parallelScavenge搭配(serialOld和parallelOld)、CMS并發(fā)模式失敗后以serialOld做備份
4)CMS
1、運作步驟
初始標(biāo)記(stop?the?world)、并發(fā)標(biāo)記、重新標(biāo)記(stop?the?world)、并發(fā)清除
2、優(yōu)點
并發(fā)收集、低停頓
3、缺點
CMS收集器對CPU資源非常敏感
CMS收集器無法處理浮動垃圾(Concurrent?Mode?Failure)
CMS收集器會產(chǎn)生大量空間碎片
5)G1
1、特點
并行于并發(fā)、空間整合、可預(yù)測的停頓、分代收集
2、運作步驟
初始標(biāo)記、并發(fā)標(biāo)記、最終標(biāo)記、篩選回收
(4)垃圾回收機制
1)GC觸發(fā)的條件
Minor GC觸發(fā)條件:當(dāng)Eden區(qū)滿時,觸發(fā)Minor GC
Full GC觸發(fā)條件:
1、調(diào)用System.gc時,系統(tǒng)建議執(zhí)行Full GC,但是不必然執(zhí)行
2、老年代空間不足
3、方法去空間不足
4、通過Minor GC后進入老年代的平均大小大于老年代的可用內(nèi)存
5、由Eden區(qū)、From Space區(qū)向To Space區(qū)復(fù)制時,對象大小大于To Space可用內(nèi)存,則把該對象轉(zhuǎn)存到老年代,且老年代的可用內(nèi)存小于該對象大小
6、?CMS GC時出現(xiàn)promotion failed和concurrent mode failure?
2)年輕代到年老代的晉升過程的判斷條件
1、長期存活的對象進入老年代(15次MinorGC,JVM參數(shù)-XX:MaxTenuringThreshold)
2、動態(tài)對象年齡判定(大于等于某個年齡的對象超過了survivor空間一半)
3、如果對象的大小大于Eden的二分之一會直接分配在old,如果old也分配不下,會做一次majorGC。如果小于eden的一半但是沒有足夠的空間,就進行minor gc也就是新生代GC,minor gc后,survivor仍然放不下,則放到老年代
3)一次完整的 GC 流程
1.大對象直接進入到老年代
2.小對象先在eden區(qū)分配內(nèi)存,當(dāng)eden滿了后,觸發(fā)一次Minor GC,清理eden區(qū)域
3.存活下來的對象進入到survivor區(qū)域,年齡+1
4.當(dāng)年齡>15(默認(rèn))時進入到老年代,當(dāng)老年代滿了后觸發(fā)一次Full GC
4)fullGC 很頻繁,線上排查問題
查看gc.log
?jmap -histo:live pid
-XX:+HeapDumpBeforeFullGC
jstat?-gcutil?pid
四、jvm分析
(1)jvm命令工具
jstack
jmap
jhat
jstat
jinfo
jps
jconsole, jvisualvm
(2)線程堆棧
1)線程堆棧信息
線程的名字、線程的優(yōu)先級、線程 id、線程的狀態(tài)、線程占用的內(nèi)存地址、線程的調(diào)用棧
2)線程狀態(tài)
NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
3)分析性能問題
1、系統(tǒng)無緣無故的cpu過高
2、系統(tǒng)掛起,無響應(yīng)
3、系統(tǒng)運行越來越慢
4、性能瓶頸(如無法充分利用cpu等)
5、線程死鎖,死循環(huán)等
6、由于線程數(shù)量太多導(dǎo)致的內(nèi)存溢出(如無法創(chuàng)建線程等)
五、類加載
(1)雙親委派模型
類加載器:Bootstrap、Extension、Application
(2)打破雙親加載
JNDI、JDBC、Tomcat
(3)類加載過程
裝載、鏈接(驗證、準(zhǔn)備、解析)、初始化、使用、卸載
(4)類的實例化順序
父類靜態(tài)變量->父類靜態(tài)代碼塊->子類靜態(tài)變量->子類的靜態(tài)代碼塊->父類成員變量->父類代碼塊->父類構(gòu)造方法->子類成員變量->子類代碼塊->子類構(gòu)造方法
(5)類裝載方式
1)隱式裝載
創(chuàng)建類對象、使用類的靜態(tài)域、創(chuàng)建子類對象、使用子類的靜態(tài)域。
其他特殊的隱式加載:
在JVM啟動時,BootStrapLoader會加載一些JVM自身運行所需的class
在JVM啟動時,ExtClassLoader會加載指定目錄下一些特殊的class
在JVM啟動時,AppClassLoader會加載classpath路徑下的class,以及main函數(shù)所在的類的class文件
2)顯式裝載
ClassLoader.loadClass(className) :只執(zhí)行裝載過程。
Class.forName(className):執(zhí)行類的裝載、鏈接、初始化過程
注:1、Class.forName(className)是初始化類,newInstance()是實例化類。new是初始化加實例化類。2、new關(guān)鍵字和Class類的newInstance()的區(qū)別
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的Java JVM总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 春种一粒粟的下一句 下一句是秋收万颗子
- 下一篇: Java 并发总结——高并发与同步锁