摘要:一多個(gè)類的初始化在進(jìn)入正文前首先根據(jù)上面的例子試圖猜測(cè)為了類中的函數(shù)能夠運(yùn)行需要做哪些前置工作呢這些工作是以什么順序展開的呢為了更好的描述多個(gè)類的情形可以先試圖描述一個(gè)更簡(jiǎn)單的例子把行和行和行注釋掉二類從到一句話把類從介質(zhì)中復(fù)制到方法區(qū)通過
一)Example: 多個(gè)類的初始化
package me; class A { static int a = 1; static { a = 2; System.out.print("A init"); } static int getA(){ return a; } } class B extends A{ static int b = 1; static { b = 2; System.out.print("B init"); } } class Main { static public void main(String... args){ System.out.print(A.a);//0 System.out.print(B.a);//1 System.out.print(B.getA());//2 System.out.print(B.b);//3 } }
在進(jìn)入正文前,首先根據(jù)上面的例子試圖猜測(cè):為了Main類中的main()函數(shù)能夠運(yùn)行,JVM需要做哪些前置工作呢?這些工作是以什么順序展開的呢?
為了更好的描述多個(gè)類的情形,可以先試圖描述一個(gè)更簡(jiǎn)單的例子:把行1和行2和行3注釋掉.
一句話: 把類從介質(zhì)中復(fù)制到JVM方法區(qū),通過各種規(guī)則驗(yàn)證和符號(hào)解析,最后根據(jù)程序員的邏輯賦值或其他語句完成初始化
Step1.類的加載(Loading)加載是把存儲(chǔ)類的實(shí)體從各類介質(zhì)(文件/網(wǎng)絡(luò)/數(shù)據(jù)庫(kù)/內(nèi)存中實(shí)時(shí)生成等)加載到JVM的方法區(qū)中的過程,主要包含2步:
根據(jù)類的全限定名"me.B"通過 _ApplicationClassLoader_(或者是自己定義的ClassLoader)獲得B類的二進(jìn)制流
把流讀入內(nèi)存中,并轉(zhuǎn)化為JVM規(guī)定的方法區(qū)結(jié)構(gòu),生成對(duì)應(yīng)的java.lang.Class對(duì)象
現(xiàn)在,你可以在程序中訪問到這個(gè)類~(≧▽≦)/~啦
Step2.類的連接(Linking)JVM中的連接細(xì)分為獨(dú)立的3步:驗(yàn)證/準(zhǔn)備/解析
驗(yàn)證和準(zhǔn)備的開始是有嚴(yán)格的順序的,但是JVM可以自由選擇解析發(fā)生的時(shí)機(jī),甚至放到初始化之后
Step3.驗(yàn)證(Validation)連接可以理解為把源代碼轉(zhuǎn)化為可執(zhí)行程序的過程,當(dāng)然不同于C/C++連接生成的.exe程序,JVM中的可執(zhí)行程序一般是字節(jié)碼(bytecode)程序
驗(yàn)證過程較為復(fù)雜,JVM主要驗(yàn)證了class文件格式/java語義限制/java程序邏輯正確性和安全性,其主要技術(shù)為靜態(tài)的字節(jié)碼分析,所以不能保證100%的可靠
Step4.準(zhǔn)備(Preparation)為me.B類中的靜態(tài)變量int b在堆中分配內(nèi)存,并設(shè)置其初始值0
Step5.解析(Resolution)簡(jiǎn)單地說,是將符號(hào)引用轉(zhuǎn)化為直接引用的過程,所有符號(hào)引用都必須轉(zhuǎn)化為直接引用
Step6.類的初始化(Initialization)符號(hào)引用: 如方法名/變量名/類等等的符號(hào)
直接引用: 直接指向一塊內(nèi)存區(qū)域
在初始化之前,程序已經(jīng)可以在內(nèi)存中訪問到me.B類和其類變量了
初始化所做的事情也很簡(jiǎn)單:JVM從上到下收集類變量賦值語句和類靜態(tài)初始化塊中的語句,把它放到JVM生成的
對(duì)于初始化的時(shí)機(jī),JVM有嚴(yán)格的規(guī)范:只有在主動(dòng)引用時(shí)才會(huì)觸發(fā)類的初始化
主動(dòng)引用有5種情況:大致可以理解為以下幾種
以各種方式讀靜態(tài)變量/寫靜態(tài)變量/觸發(fā)靜態(tài)方法時(shí)(包括出現(xiàn)相應(yīng)的字節(jié)碼指令/反射/invokedynamic)類卻沒有初始化
包含入口方法main()的類
初始化子類時(shí)父類還沒初始化
其他情況都是被動(dòng)引用
可以看到,me.B的
b = 1; b = 2; System.out.print("B init");三)類:從1到n再到0 類的使用(Using)
類的實(shí)例化過程,包括new/反射等方法
類的卸載(Unloading)當(dāng)程序中無論什么方法都無法引用該類時(shí),類從方法區(qū)被回收,大致可以理解為
類的所有實(shí)例被回收
類的ClassLoader被回收
沒有地方引用Class對(duì)象,也無法通過反射訪問
四)Example:執(zhí)行過程簡(jiǎn)述回到最初的例子,可以列出預(yù)計(jì)的執(zhí)行順序?yàn)?
初始化me.Main
加載me.B
初始化me.A: 輸出"A init"
System.out.print(A.a);:輸出2
System.out.print(B.a);:輸出2
System.out.print(B.getA());:輸出2
初始化me.B:輸出"B init"
System.out.print(B.b);:輸出2
實(shí)際執(zhí)行結(jié)果驗(yàn)證:
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67281.html
摘要:原文地址游客前言金三銀四,很多同學(xué)心里大概都準(zhǔn)備著年后找工作或者跳槽。最近有很多同學(xué)都在交流群里求大廠面試題。 最近整理了一波面試題,包括安卓JAVA方面的,目前大廠還是以安卓源碼,算法,以及數(shù)據(jù)結(jié)構(gòu)為主,有一些中小型公司也會(huì)問到混合開發(fā)的知識(shí),至于我為什么傾向于混合開發(fā),我的一句話就是走上編程之路,將來你要學(xué)不僅僅是這些,豐富自己方能與世接軌,做好全棧的裝備。 原文地址:游客kutd...
摘要:極力推薦文章歡迎收藏干貨分享閱讀五分鐘,每日十點(diǎn),和您一起終身學(xué)習(xí),這里是程序員本篇文章主要介紹開發(fā)中的部分知識(shí)點(diǎn),通過閱讀本篇文章,您將收獲以下內(nèi)容生命周期簡(jiǎn)介必須在中注冊(cè)啟動(dòng)的方法啟動(dòng)帶返回值的結(jié)束方法狀態(tài)保存,恢復(fù)的方法面 showImg(https://upload-images.jianshu.io/upload_images/5851256-0b56fc8e812963d7...
摘要:并總結(jié)經(jīng)典面試題集各種算法和插件前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快速搭建項(xiàng)目。 本文是關(guān)注微信小程序的開發(fā)和面試問題,由基礎(chǔ)到困難循序漸進(jìn),適合面試和開發(fā)小程序。并總結(jié)vue React html css js 經(jīng)典面試題 集各種算法和插件、前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快...
閱讀 1059·2021-10-11 10:59
閱讀 3610·2021-09-26 09:55
閱讀 906·2019-08-30 15:55
閱讀 2659·2019-08-30 15:44
閱讀 443·2019-08-30 14:06
閱讀 689·2019-08-30 11:26
閱讀 3349·2019-08-30 10:49
閱讀 2499·2019-08-29 12:53