1. 程式人生 > >JVM類載入機制(ClassLoader)原始碼解析(1)

JVM類載入機制(ClassLoader)原始碼解析(1)

其實JVM類載入機制,簡單地說就是類管理,也就是我們生成的class檔案。
三個步驟:裝載(load)、連結(link)、解析(Resolve)、還有初始化(Initialize)
關於網上有很多講解載入的方式,和呼叫的方式,還是幾個基本的classLoader,這裡就不在多描述了。
這裡更多的是從原始碼上來講解,達到理論結合實際。

首先是ClassLoader這個抽象類,這個是實現自定義類的基礎。那麼在呼叫的時候,首先都是呼叫loadClass這個方法,如圖:

該方法呼叫的是一個過載方法loadClass(name,false)方法如圖:

第一行註釋很清楚的表示,從當前的類載入器里加載class檔案,如果已經載入,就直接返回;不存在就載入;如果返回NULL,表示class檔案不在這個類載入器的範圍內。
這是就會執行if(c==null)下面的方法,就會去找父載入器(類載入器的整個結構是樹形的,這裡不多介紹),如果父載入器不存在,就直接找到根載入器(根載入器一定存在)。
我們現在開始解析每個被呼叫方法。
首先看下findLoadedClass

方法,如圖:

該方法首先,校驗類名是否正確(類似於 test.demo.Test.class),校驗成功後,呼叫本地方法findLoadedClass0方法。

接著是parent.loadClass(name,false)方法,該方法是重複的,只是物件不同而已,就不介紹了。
接著是findBootstrapClassOrNull方法,如圖:

方式與findLoadedClass方法一樣,就是本地呼叫是findBootstrapClass方法。
如果此時類還不存在,有一個findClass方法的呼叫。程式碼如圖:

這裡看上去覺得很奇怪,直接就拋一個空異常了,其實根據註釋所說,就是自定義的類載入器需要實現這種方法。
為什麼要實現這個方法呢?原因就是有些場景會需要通過網路傳輸的方式進行載入類(該類其實是在遠端伺服器上的),在很多地方就會用到,例如遠端呼叫等技術。
具體的實現例子,在URLClassLoader裡就有體現,這裡暫不介紹。

最後是呼叫了resolveClass
方法,程式碼如圖:

這個方法很簡單,主要是重新進行解析類,該解析主要是對所有的屬性/方法呼叫是否存在、相應的許可權(如private、public等)進行驗證。那麼為什麼預設都是傳入false呢?
那是因為是否需要更強的安全機制的檢測,
另一個情況是類載入是無序的,會導致類連結不成功。
這裡有個狀態位的控制,主要是可能有些場景需要更嚴格的對類進行驗證(目前我還沒有使用到這樣的場景)。

這裡要注意的是:
類為什麼是樹形結構,主要就是安全,因為類載入器都是從不同的目錄進行載入的(網上有介紹三個最基礎的類載入器Bootstrap ClassLoader\Extension ClassLoader\System ClassLoader載入的預設目錄,這裡不多介紹),所以用這種目錄的方式來進行許可權管理,常用都是使用classpath系統變數,如果我想自己定義一個載入目錄,那麼就需要實現自己的類載入器,進行相應的許可權管理。
另外這個抽象類,實現了只是從本地進行載入類的方式,如果需要進行遠端載入類,那麼也需要實現自己的類載入器。

這裡是類載入器的基本功能介紹,裡面還有如何載入native Library 方法、class檔案/包名相關安全驗證等,在後續會繼續介紹。