6.虚拟机类加载机制
1.什么是類加載
把描述類的數據從class(這里的class不僅僅只class文件,任何方式都可以,比如說jar包,反射等)文件加載到內存,并對數據進行校驗,轉換解析和初始換,最終形成可以被虛擬機直接說使用的java類型。
2.java虛擬機中類加載的全過程
加載(這個加載指的是類加載的一個階段,不是類加載),驗證,準備,初始化和卸載這5個階段的順序是確定的,但是解析階段則不一定,這是為了支持java語言的運行時綁定。
什么情況下需要開始類加載過程的第一個階段:加載?
創建類的實例,訪問類的靜態變量,訪問類的靜態方法,如果之前沒有進行過初始化,則要先觸發初始化。
反射?如(java.lang.reflect報的方法:?Class.forName("my.xyz.Test")?)
當初始化一個類時,發現其父類還未初始化,則先出發父類的初始化
虛擬機啟動時,定義了main()方法的那個類先初始化
?2.1加載:
?1、?通過一個類的全限定名來獲取定義此類的二進制字節流。(可以從任何地方獲取,并不一定要是class文件)
? ? ? ?2、?將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構。
? ? ? ?3、?在Java堆中生成一個代表這個類的java.lang.Class對象,作為方法區這些數據的訪問入口。
2.2.驗證:
驗證輸入的字節流是否合法
2.3.準備階段:
正式為類變量分配內存并設置類變量初始值的階段(如int型的變量初始值為0等,final特殊),所使用的內存在方法區中分配。
2.4.解析:
將虛擬機常量池內的符號引用替換為直接引用(大概意思就是將“描述地址的唯一標識”轉化為真正的指針)
2.5.初始化:
類加載的最后一步,也就是執行類構造器方法的過程
3.類加載器
類加載階段中的“通過一個類的全限定名來獲取描述此類的二進制字節流”這個動作放到java虛擬機外部實現,一邊應用程序自己決定如何去獲取所需要的類。實現這個動作的代碼模塊稱為“類加載器”。
3.1.類與類加載器
對于任意一個類,都需要由加載它的類加載器和這個類本身一同確立其在java虛擬機中的唯一性,也就是比較兩個類“相等”,只有在這兩個類是由同一個類加載器加載的前提才有意義
3.2.雙親委派模型
類加載器類型:
從虛擬機角度來講:啟動類加載器(bootstrap classloader)和其他實現了java.lang.classloader的類加載器。
從程序員角度看:
啟動類加載器(Bootstrap ClassLoader):用于加載Java?API,加載<JAVA_HOME>\lib目錄下的類庫。
擴展類加載類(Extension ClassLoader):由sun.misc.Launcher$ExtClassLoader實現,用于加載<JAVA_HOME>\lib\ext目錄下或者被java.ext.dirs系統變量指定路徑下的類庫。
應用程序類加載器(Application ClassLoader):也成為系統類加載器,由sun.misc.Launcher$AppClassLoader實現,用于加載用戶類路徑(ClassPath)上所指定的類庫。
自定義類加載器:實現用戶自定義加載邏輯。
下圖這種關系被稱為:雙親委派模型
雙親委派模型要求除了頂層的啟動類加載器之外,其余的類加載器都應該有自己的父類加載器。
各個類加載器之間是組合關系,并非繼承關系。
雙親委派模型的工作過程:
當一個類加載器收到類加載的請求,它將這個加載請求委派給父類加載器進行加載,每一層加載器都是如此,最終,所有的請求都會傳送到啟動類加載器中。只有當父類加載器自己無法完成加載請求時,子類加載器才會嘗試自己加載。
優點:
雙親委派模型可以確保安全性,可以保證所有的Java類庫都是由啟動類加載器加載。如用戶編寫的java.lang.Object,加載請求傳遞到啟動類加載器,啟動類加載的是系統中的Object對象,而用戶編寫的java.lang.Object不會被加載。如用戶編寫的java.lang.virus類,加載請求傳遞到啟動類加載器,啟動類加載器發現virus類并不是核心Java類,無法進行加載,將會由具體的子類加載器進行加載,而經過不同加載器進行加載的類是無法訪問彼此的。由不同加載器加載的類處于不同的運行時包。所有的訪問權限都是基于同一個運行時包而言的。
3.3.破壞雙親委派模型
第一次“被破壞”發生在雙親委派模型出現之前。親委派模型在JDK 1.2 之后才被引入,類加載器和抽象類Java. lang. ClassLoader 則在JDK 1 .0 時代就已經存在,對已經存在的用戶自定義類加載器的實現代碼, Java 設計者們引入雙親委派模型時做出了一些妥協。?
第二次“被破壞”是由這個模型自身的缺陷所導致的,雙親委派很好地解決了各個類加載器的基礎類的統一問題(越基礎的類由越上層的類加載器進行加載),基礎類之所以被稱為“基礎”,是因為它們總是作為被用戶代碼詞用的API。但是基礎類有時又要調用用戶代碼,如JNDI。此時就引入了線程上下文類加器。?
第三次“被破壞”是由于用戶對程序動態性的追求而導致的。代碼熱替換(HotSwap)、模塊熱部署(Hot Deployment)等?
轉載于:https://blog.51cto.com/13175699/1955128
總結
以上是生活随笔為你收集整理的6.虚拟机类加载机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Rancher upgrade webh
- 下一篇: Ajax请求导出Excel的问题