做了這么多年Java,Java程序的執(zhí)行順序知道嗎?

Java字節(jié)代碼:byte[]

Java類在JVM的表現(xiàn)形式:Class類的對(duì)象;

Java源代碼被編譯成class字節(jié)碼 :

Java字節(jié)代碼 --> Class類的對(duì)象:

加載:把Java字節(jié)碼byte[]轉(zhuǎn)換成JVM中的java.lang.Class類的對(duì)象;

鏈接:Java類的鏈接指的是將Java類的二進(jìn)制代碼合并到JVM的運(yùn)行狀態(tài)之中的過程。

初始化:主要是執(zhí)行靜態(tài)代碼塊初始化靜態(tài)域

Java類的加載

作用 ?{想學(xué)習(xí)Java的請(qǐng)留言 有資料分享}

把Java字節(jié)碼轉(zhuǎn)換成JVM中的java.lang.Class類的對(duì)象;

通過一個(gè)類的全限定名獲取描述此類的二進(jìn)制字節(jié)流;

將這個(gè)字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)保存為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu);

在java堆中生成一個(gè)代表這個(gè)類的java.lang.Class對(duì)象,作為訪問方法區(qū)的入口;

類加載器分類

啟動(dòng)類加載器(Bootstrap ClassLoader):負(fù)責(zé)加載?JAVA_HOME\lib?目錄中的,或通過-Xbootclasspath參數(shù)指定路徑中的,且被虛擬機(jī)認(rèn)可(按文件名識(shí)別,如rt.jar)的類;

擴(kuò)展類加載器(Extension ClassLoader):負(fù)責(zé)加載?JAVA_HOME\lib\ext?目錄中的,或通過java.ext.dirs系統(tǒng)變量指定路徑中的類庫;

應(yīng)用程序類加載器(Application ClassLoader):負(fù)責(zé)加載用戶路徑(classpath)上的類庫;

雙親委派模型工作過程:

當(dāng)一個(gè)類加載器收到類加載任務(wù),優(yōu)先交給其父類加載器去完成,因此最終加載任務(wù)都會(huì)傳遞到頂層的啟動(dòng)類加載器,只有當(dāng)父類加載器無法完成加載任務(wù)時(shí),才會(huì)嘗試執(zhí)行加載任務(wù)。

雙親委派模型有什么好處?

比如位于rt.jar包中的類java.lang.Object,無論哪個(gè)加載器加載這個(gè)類,最終都是委托給頂層的啟動(dòng)類加載器進(jìn)行加載,確保了Object類在各種加載器環(huán)境中都是同一個(gè)類。

重要特征

層次組織結(jié)構(gòu):每個(gè)類加載器都有一個(gè)父類加載器,形成tree結(jié)構(gòu);

代理模式:一個(gè)類加載器既可以自己完成Java類的定義工作,也可以代理給其它的類加載器來完成;

Java類的鏈接

Java類的鏈接指的是將Java類的二進(jìn)制代碼合并到JVM的運(yùn)行狀態(tài)之中的過程。

包含的步驟:

驗(yàn)證:確保Java類的二進(jìn)制表示在結(jié)構(gòu)上是完全正確的,主要包括格式驗(yàn)證、元數(shù)據(jù)驗(yàn)證、字節(jié)碼驗(yàn)證和符號(hào)引用驗(yàn)證;

準(zhǔn)備:創(chuàng)建Java類中的靜態(tài)域,并將這些域的值設(shè)為默認(rèn)值;

在準(zhǔn)備階段,為類變量(static修飾)在方法區(qū)中分配內(nèi)存并設(shè)置初始值。

private static int var = 100;

準(zhǔn)備階段完成后,var值為0,而不是100。在初始化階段,才會(huì)把100賦值給val,但是有個(gè)特殊情況:

private static final int VAL= 100;

在編譯階段會(huì)為VAL生成ConstantValue屬性,在準(zhǔn)備階段虛擬機(jī)會(huì)根據(jù)ConstantValue屬性將VAL賦值為100。

解析:解析階段是將常量池中的符號(hào)引用替換為直接引用的過程,解析過程可能導(dǎo)致其他的Java類被加載;

符號(hào)引用使用一組符號(hào)來描述所引用的目標(biāo),可以是任何形式的字面常量,定義在Class文件格式中。

直接引用可以是直接指向目標(biāo)的指針、相對(duì)偏移量或則能間接定位到目標(biāo)的句柄。

Java類的初始化

初始化階段是執(zhí)行類構(gòu)造器clinit方法的過程,clinit方法由類變量的賦值動(dòng)作和靜態(tài)語句塊按照在源文件出現(xiàn)的順序合并而成,該合并操作由編譯器完成。

方法clinit對(duì)于類或接口不是必須的,如果一個(gè)類中沒有靜態(tài)代碼塊,也沒有靜態(tài)變量的賦值操作,那么編譯器不會(huì)生成

方法clinit方法與實(shí)例構(gòu)造器不同,不需要顯式的調(diào)用父類的

為了防止多次執(zhí)行clinit,虛擬機(jī)會(huì)確保clinit方法在多線程環(huán)境下被正確的加鎖同步執(zhí)行,如果有多個(gè)線程同時(shí)初始化一個(gè)類,那么只有一個(gè)線程能夠執(zhí)行clinit方法,其它線程進(jìn)行阻塞等待,直到clinit執(zhí)行完成。

注意:執(zhí)行接口的clinit方法不需要先執(zhí)行父接口的clinit,只有使用父接口中定義的變量時(shí),才會(huì)執(zhí)行。

初始化過程的主要操作是執(zhí)行靜態(tài)代碼塊初始化靜態(tài)域。

在一個(gè)類被初始化之前,它的直接父類也需要被初始化。

類初始化場景

虛擬機(jī)中嚴(yán)格規(guī)定了有且只有5種情況必須對(duì)類進(jìn)行初始化。

執(zhí)行new、getstatic、putstatic和invokestatic指令;

使用reflect對(duì)類進(jìn)行反射調(diào)用;

初始化一個(gè)類的時(shí)候,父類還沒有初始化,會(huì)事先初始化父類;

啟動(dòng)虛擬機(jī)時(shí),需要初始化包含main方法的類;

在JDK1.7中,如果java.lang.invoke.MethodHandler實(shí)例最后的解析結(jié)果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且這個(gè)方法句柄對(duì)應(yīng)的類沒有進(jìn)行初始化;

不會(huì)觸發(fā)類初始化的情況

通過子類引用父類的靜態(tài)字段,只會(huì)觸發(fā)父類的初始化,而不會(huì)觸發(fā)子類的初始化。

輸出結(jié)果為:parent init! 不會(huì)初始化Child類。

定義對(duì)象數(shù)組,不會(huì)觸發(fā)該類的初始化。

常量在編譯期間會(huì)存入調(diào)用類的常量池中,本質(zhì)上并沒有直接引用定義常量的類,不會(huì)觸發(fā)定義常量所在的類。

在編譯階段,Const類中常量A的值100存儲(chǔ)到Init類的常量池中,這兩個(gè)類在編譯成class文件之后就沒有聯(lián)系了。

通過類名獲取Class對(duì)象,不會(huì)觸發(fā)類的初始化。

通過Class.forName加載指定類時(shí),如果指定參數(shù)initialize為false時(shí),也不會(huì)觸發(fā)類初始化,其實(shí)這個(gè)參數(shù)是告訴虛擬機(jī),是否要對(duì)類進(jìn)行初始化

通過ClassLoader默認(rèn)的loadClass方法,也不會(huì)觸發(fā)初始化動(dòng)作;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 YY:Kitty,我最近在看Thinking in Java 這本書Kitty:喔?是么,你不是一直覺得那本...
    LilacZiyun閱讀 5,665評(píng)論 10 51
  • 這篇文章是我之前翻閱了不少的書籍以及從網(wǎng)絡(luò)上收集的一些資料的整理,因此不免有一些不準(zhǔn)確的地方,同時(shí)不同JDK版本的...
    高廣超閱讀 16,057評(píng)論 3 83
  • 我太累了。 不是因?yàn)槔?,而是因?yàn)楹翢o意義。 我也已經(jīng)盡心盡力了。 我不能變成那個(gè)人,所以我得做準(zhǔn)備了。
    ZML1024閱讀 104評(píng)論 0 0
  • 小說講述的是一個(gè)從小與大自然結(jié)緣的女子,唐清沅,獨(dú)自一人前往荒無人跡的失望島,研究信天翁,并與肖恩的一段腦電波...
    煙雨斜陽若依閱讀 1,293評(píng)論 1 4
  • 小籠包的媽媽今年才26歲,結(jié)婚一年,門上的大紅喜字還沒撕掉 她懷上了小籠包,卻得了癌癥,人生就像一個(gè)牌局,她不幸抽...
    山風(fēng)欲來閱讀 60,015評(píng)論 0 1

友情鏈接更多精彩內(nèi)容