面試官:今天從基礎先問起吧,你是怎么理解Java是一門「跨平臺」的語言,也就是「一次編譯,到處運行的」?
候選者:很好理解啊,因為我們有JVM,
候選者:Java源代碼會被編譯為class檔案,class檔案是運行在JVM之上的,
候選者:當我們日常開發安裝JDK的時候,可以發現JDK是分「不同的作業系統」,JDK里是包含JVM的,所以Java依賴著JVM實作了『跨平臺』
候選者:JVM是面向作業系統的,它負責把Class位元組碼解釋成系統所能識別的指令并執行,同時也負責程式運行時記憶體的管理,

面試官:那要不你來聊聊從原始碼檔案(.java)到代碼執行的程序唄?
候選者:嗯,沒問題的
候選者:簡單總結的話,我認為就4個步驟:編譯->加載->解釋->執行
候選者:編譯:將原始碼檔案編譯成JVM可以解釋的class檔案,
候選者:編譯程序會對源代碼程式做 「語法分析」「語意分析」「注解處理」等等處理,最后才生成位元組碼檔案,
候選者:比如對泛型的擦除和我們經常用的Lombok就是在編譯階段干的,

候選者:加載:將編譯后的class檔案加載到JVM中,
候選者:在加載階段又可以細化幾個步驟:裝載->連接->初始化
候選者:下面我對這些步驟又細說下哈,

候選者:【裝載時機】為了節省記憶體的開銷,并不會一次性把所有的類都裝載至JVM,而是等到「有需要」的時候才進行裝載(比如new和反射等等)
候選者:【裝載發生】class檔案是通過「類加載器」裝載到jvm中的,為了防止記憶體中出現多份同樣的位元組碼,使用了雙親委派機制(它不會自己去嘗試加載這個類,而是把請求委托給父加載器去完成,依次向上)
候選者:【裝載規則】JDK 中的本地方法類一般由根加載器(Bootstrp loader)裝載,JDK 中內部實作的擴展類一般由擴展加載器(ExtClassLoader )實作裝載,而程式中的類檔案則由系統加載器(AppClassLoader )實作裝載,
候選者:裝載這個階段它做的事情可以總結為:查找并加載類的二進制資料,在JVM「堆」中創建一個java.lang.Class類的物件,并將類相關的資訊存盤在JVM「方法區」中
面試官:嗯...
候選者:通過「裝載」這個步驟后,現在已經把class檔案裝載到JVM中了,并創建出對應的Class物件以及類資訊存盤至方法區了,
候選者:「連接」這個階段它做的事情可以總結為:對class的資訊進行驗證、為「類變數」分配記憶體空間并對其賦默認值,
候選者:連接又可以細化為幾個步驟:驗證->準備->決議
候選者:1. 驗證:驗證類是否符合 Java 規范和 JVM 規范
候選者:2. 準備:為類的靜態變數分配記憶體,初始化為系統的初始值
候選者:3. 決議:將符號參考轉為直接參考的程序
面試官:嗯...
候選者:通過「連接」這個步驟后,現在已經對class資訊做校驗并分配了記憶體空間和默認值了,
候選者:接下來就是「初始化」階段了,這個階段可以總結為:為類的靜態變數賦予正確的初始值,
候選者:程序大概就是收集class的靜態變數、靜態代碼塊、靜態方法至
候選者:如果「實體化物件」則會呼叫方法對實體變數進行初始化,并執行對應的構造方法內的代碼,

候選者:扯了這么多,現在其實才完成至(編譯->加載->解釋->執行)中的加載階段,下面就來說下【解釋階段】做了什么
候選者:初始化完成之后,當我們嘗試執行一個類的方法時,會找到對應方法的位元組碼的資訊,然后解釋器會把位元組碼資訊解釋成系統能識別的指令碼,
候選者:「解釋」這個階段它做的事情可以總結為:把位元組碼轉換為作業系統識別的指令
候選者:在解釋階段會有兩種方式把位元組碼資訊解釋成機器指令碼,一個是位元組碼解釋器、一個是即時編譯器(JIT),

候選者:JVM會對「熱點代碼」做編譯,非熱點代碼直接進行解釋,當JVM發現某個方法或代碼塊的運行特別頻繁的時候,就有可能把這部分代碼認定為「熱點代碼」
候選者:使用「熱點探測」來檢測是否為熱點代碼,「熱點探測」一般有兩種方式,計數器和抽樣,HotSpot使用的是「計數器」的方式進行探測,為每個方法準備了兩類計數器:方法呼叫計數器和回邊計數器
候選者:這兩個計數器都有一個確定的閾值,當計數器超過閾值溢位了,就會觸發JIT編譯,
候選者:即時編譯器把熱點方法的指令碼保存起來,下次執行的時候就無需重復的進行解釋,直接執行快取的機器語言
面試官:嗯...
候選者:解釋階段結束后,最后就到了執行階段,
候選者:「執行」這個階段它做的事情可以總結為:作業系統把解釋器決議出來的指令碼,呼叫系統的硬體執行最終的程式指令,
候選者:上面就是我對從原始碼檔案(.java)到代碼執行的程序的理解了,
面試官:嗯...我還想問下你剛才提到的雙親委派模型...
候選者:下次一定!

本文總結:
- Java跨平臺因為有JVM屏蔽了底層作業系統
- Java原始碼到執行的程序,從JVM的角度看可以總結為四個步驟:編譯->加載->解釋->執行
- 「編譯」經過 語法分析、語意分析、注解處理 最后才生成會class檔案
- 「加載」又可以細分步驟為:裝載->連接->初始化,裝載則把class檔案裝載至JVM,連接則校驗class資訊、分配記憶體空間及賦默認值,初始化則為變數賦值為正確的初始值,連接里又可以細化為:驗證、準備、決議
- 「解釋」則是把位元組碼轉換成作業系統可識別的執行指令,在JVM中會有位元組碼解釋器和即時編譯器,在解釋時會對代碼進行分析,查看是否為「熱點代碼」,如果為「熱點代碼」則觸發JIT編譯,下次執行時就無需重復進行解釋,提高解釋速度
- 「執行」呼叫系統的硬體執行最終的程式指令

歡迎關注我的微信公眾號【Java3y】來聊聊Java面試,對線面試官系列持續更新中!
【對線面試官-移動端】系列 一周兩篇持續更新中!
【對線面試官-電腦端】系列 一周兩篇持續更新中!
原創不易!!求三連!!
更多的文章可往:文章的目錄導航轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/320864.html
標籤:其他
上一篇:2-3-4樹對應紅黑樹的實作,紅黑樹的融會貫通!!!
下一篇:Python字典和集合
