JVM调优系列:(三)类加载和执行机制
類加載機(jī)制
JVM的類加載是通過ClassLoader及其子類來完成的,類的層次關(guān)系和加載順序可以由下圖來描述:
每個(gè)ClassLoader加載Class的過程是:
1.檢測此Class是否載入過(即在cache中是否有此Class),如果有到8,如果沒有到2
2.如果parent classloader不存在(沒有parent,那parent一定是bootstrap),到4
3.請(qǐng)求parent classloader載入,如果成功到8,不成功到5
4.請(qǐng)求jvm從bootstrap classloader中載入,如果成功到8
5.尋找Class文件(從與此classloader相關(guān)的類路徑中尋找)。如果找不到則到7.
6.從文件中載入Class,到8.
7.拋出ClassNotFoundException.
8.返回Class.
?
?類執(zhí)行機(jī)制
JVM的指令是從操作數(shù)棧中取得操作數(shù),是基于棧的體系結(jié)構(gòu)來執(zhí)行class字節(jié)碼的。線程創(chuàng)建后,都會(huì)產(chǎn)生程序計(jì)數(shù)器(PC)和棧(Stack),程序計(jì)數(shù)器存放下一條要執(zhí)行的指令在方法內(nèi)的偏移量,棧中存放一個(gè)個(gè)棧幀,每個(gè)棧幀對(duì)應(yīng)著每個(gè)方法的每次調(diào)用,而棧幀又是有局部變量區(qū),操作數(shù)棧和幀數(shù)據(jù)區(qū)組成,局部變量區(qū)用于存放方法中的局部變量和參數(shù),操作數(shù)棧中用于存放方法執(zhí)行過程中產(chǎn)生的中間結(jié)果。局部變量區(qū)和操作數(shù)棧的大小,編譯器在編譯時(shí)就確定了存放在class文件中.而幀數(shù)據(jù)區(qū)大小依賴于具體實(shí)現(xiàn),這些信息用來支持常量池解析,正常方法返回以及異常派發(fā)機(jī)制.
?
32位HotSpot上要求64位/8字節(jié)對(duì)齊,HotSpot在C++代碼中用instanceOopDesc類來表示Java對(duì)象,而該類繼承oopDesc,oopDesc保存了java class的元數(shù)據(jù)信息,而Klass保存了java class的實(shí)際數(shù)據(jù)。klass就是用于描述GC堆上的對(duì)象的對(duì)針;如果一個(gè)對(duì)象的大小、域的個(gè)數(shù)與類型等信息不固定的話,它就需要特定的klass對(duì)象來描述。
instanceOopDesc用于表示Java對(duì)象,instanceKlass用于描述它,HotSpot并不把instanceKlass暴露給Java,而會(huì)另外創(chuàng)建對(duì)應(yīng)的java.lang.Class對(duì)象,兩者之間互相持有引用,如果自身卻又有些不固定的信息需要被描述,因而又有instanceKlassKlass,如此下去會(huì)沒完沒了,所以有個(gè)klassKlass作為這個(gè)描述鏈上的終結(jié)符。
通過直接指針訪問對(duì)象,klass的關(guān)系圖:
在java中的引用主要有四種:
Strong?reference:
強(qiáng)引用是JAVA中默認(rèn)采用的一種方式,它會(huì)盡可能長時(shí)間的存活于 JVM 內(nèi),當(dāng)沒有任何對(duì)象指向它時(shí) GC 執(zhí)行后將會(huì)被回收。
Soft?reference:
軟引用的對(duì)象在GC的時(shí)候不會(huì)被回收,只有當(dāng)內(nèi)存不夠用的時(shí)候才會(huì)真正的回收,因此軟引用適合緩存的場合,這樣使得緩存中的對(duì)象可以盡量的再內(nèi)存中待長久一點(diǎn)。
軟引用可以和一個(gè)引用隊(duì)列(ReferenceQueue)聯(lián)合使用,如果軟引用所引用的對(duì)象被垃圾回收,Java?虛擬機(jī)就會(huì)把這個(gè)軟引用加入到與之關(guān)聯(lián)的引用隊(duì)列中.
Weak?reference:
弱引用有利于對(duì)象更快的被回收,在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對(duì)象,不管當(dāng)前內(nèi)存空間足夠與否,都會(huì)回收它的內(nèi)存。
Phantom?reference:一個(gè)對(duì)象僅持有虛引用,那么它就和沒有任何引用一樣。虛引用主要用來跟蹤對(duì)象被垃圾回收的活動(dòng),當(dāng)垃 圾回收器準(zhǔn)備回收一個(gè)對(duì)象時(shí),如果發(fā)現(xiàn)它還有虛引用,就會(huì)在回收對(duì)象的內(nèi)存之前,把這個(gè)虛引用加入到與之關(guān)聯(lián)的引用隊(duì)列中。構(gòu)造 PhantomReference 時(shí)的第二個(gè)參數(shù) ReferenceQueue(WeakReference & SoftReference 也可以有這個(gè)參數(shù)),PhantomReference 唯一的用處就是跟蹤 referent 何時(shí)被 enqueue 到 ReferenceQueue 中.
?可復(fù)活
當(dāng)程序不再有任何引用變量引用Sample對(duì)象時(shí),它就進(jìn)入可復(fù)活狀態(tài), 垃圾回收器會(huì)準(zhǔn)備釋放它占用的內(nèi)存,在釋放之前,會(huì)調(diào)用它及其他處于可復(fù)活狀態(tài)的對(duì)象的finalize()方法。
影子可觸及
已經(jīng)被斷定不會(huì)被任何終結(jié)方法復(fù)活(終結(jié)方法已經(jīng)被運(yùn)行過了),并且影子引用對(duì)象觸及。一旦某個(gè)被影子引用的對(duì)象變成影子可觸及狀態(tài),垃圾收集器立即把該引用對(duì)象加入隊(duì)列,由程序明確地清除。
不可觸及
當(dāng)對(duì)象處于不可觸及狀態(tài)時(shí),垃圾回收器才會(huì)真正回收它們的內(nèi)存。
總結(jié)
以上是生活随笔為你收集整理的JVM调优系列:(三)类加载和执行机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM调优系列:(二)JVM运行时数据区
- 下一篇: JVM调优系列:(四)GC垃圾回收