java 类加载生命周期_Java类的加载与生命周期
一、概要:
類的生命周期從類的 加載、連接、初始化 開始,到類的 卸載結(jié)束;
二、幾個(gè)階段:
加載:查找并加載類的二進(jìn)制數(shù)據(jù)。(把類的.class文件的二進(jìn)制數(shù)據(jù)讀入內(nèi)存,存放在運(yùn)行時(shí)數(shù)據(jù)區(qū)的方法區(qū);類加載的最終結(jié)果是產(chǎn)生堆區(qū)中描述對(duì)應(yīng)類的Class對(duì)象);
連接:包括驗(yàn)證、準(zhǔn)備和解析三個(gè)子階段;
驗(yàn)證:確保補(bǔ)加載類的正確性;
準(zhǔn)備:為類的靜態(tài)變量分配內(nèi)存,并設(shè)定默認(rèn)值;
解析:把類中的符號(hào)引用轉(zhuǎn)換為直接引用;
初始化:給類中的靜態(tài)變量賦予正確的初始值;
類的加載時(shí)機(jī):并不需要等到某個(gè)類被主動(dòng)使用時(shí)才加載,虛擬機(jī)會(huì)預(yù)測某個(gè)類將要被使用就加載它;
類的初始化時(shí)機(jī):
a. 創(chuàng)建類(new、反射、克隆、反序列化)
b. 使用靜態(tài)方法、非靜態(tài)變量
c. Class.forName("ATest"); ?獲取描述類的Class對(duì)象;
另:初始化子類,父類被先初始化。虛擬機(jī)的啟動(dòng)類,使用命令 java Sample(也算是創(chuàng)建類);
注:
使用能在編譯期能得知的final static修飾的常量,不會(huì)導(dǎo)致類的初始化;
public static final int a = 2*3;//編譯時(shí)常量,不會(huì)導(dǎo)致類初始化;
public static final int a b = (int)(Math.random()*10)/10+1; // 不是編譯時(shí)常量,會(huì)初始化;
只有當(dāng)程序訪問的靜態(tài)變量或靜態(tài)方法的確在當(dāng)前類或接口中定義時(shí),才可以看作是對(duì)類或接口的主動(dòng)使用;(如用子類引用調(diào)用父類靜態(tài)方法或變量,只會(huì)初始化父類)
調(diào)用ClassLoader.loadClass()方法加載一個(gè)類時(shí),只會(huì)加載,但不會(huì)初始化;
子類父類初始化過程:
先對(duì)這個(gè)類進(jìn)行加載和連接-> 如果有直接父類,先加載連接初始化這個(gè)父類->重復(fù)以上步驟直到所有父類初始化,初始化當(dāng)前類;
(先加載連接當(dāng)前類,再加載連接初始化父類,再初始化當(dāng)前類)
classBase {static{
System.out.println("init Base");
}
}class Sub extendsBase {static{
System.out.println("init Sub");
}
}public class ATest extendsSub {static{
System.out.println("init ATest");
}public static voidmain(String args[]) {
System.out.println("main methos");
}
}
結(jié)果:
init Base
init Sub
init ATest
main methos
View Code
三、類加載器
除了Java虛擬機(jī)自帶的根類加載器以外,其余的類加載器有且只有一個(gè)父加載器;
Java虛擬機(jī)自帶以下幾種加載器:
根(Bootstrap)類加載器:沒有父類加載器。負(fù)責(zé)加載虛擬機(jī)核心類,sun.boot.class.path路徑下類庫,java.lang.*; 實(shí)現(xiàn)依賴于底層操作系統(tǒng),沒有繼承java.lang.ClassLoader;
擴(kuò)展(Extension)類加載器:父加載器為根加載器;加載java.ext.dirs下的類庫 和 JDK目錄下jre/lib/ext目錄下類庫;繼承于java.lang.ClassLoader;
系統(tǒng)(System)類加載器:也稱應(yīng)用類加載器,父加載器為擴(kuò)展類加載器;加載classpath路徑下指定的類庫;繼承于java.lang.ClassLoader,也是自定義加載器的默認(rèn)父類;
父親委托機(jī)制:
類加載過程中,會(huì)先從最頂層加載器(一般是根加載器)開始往下,先判斷父類加載器能不能加載,能加載則往下傳遞返回加載的類;不能加載則繼續(xù)往下判斷,如果都不能加載,則會(huì)拋出ClassNotFoundException異常;
加載器之間的父子關(guān)系實(shí)際上是指加載器對(duì)象之間的包裝關(guān)系,而不是類之間的繼承關(guān)系;
命名空間:
命名空間由該加載器及所有父加載器所加載的類組成;
唯一性:在同一個(gè)命名空間中,不會(huì)出現(xiàn)類的完整名字(包名+類名)相同的兩個(gè)類;
同一命名空間有以下關(guān)系:
同一命名空間的類是相互可見的;(可見是指可以直接使用其類名,不可見的類之間可以通過反射來獲取類信息);
子加載器的命名空間所含所有父加載器的命名空間,所有子類加載器的類能看見父加載器的類;但父加載器不能看見子加載器的類;
運(yùn)行時(shí)包:
包名相同,且屬于同一個(gè)類加載器;
同一運(yùn)行時(shí)包的類才能包可見;如用戶自己定義了一個(gè)java.lang.Spy,并由自己定義的類加載器加載,由于java.lang.Spy和核心類庫java.lang.*由不同的類加載器加載,它們不在同一運(yùn)行時(shí)包,Spy不能訪問java.lang.*下的包可見類;
用戶自定義類加載器:
擴(kuò)展java.lang.ClassLoader類,然后覆蓋它的findClass(String name)方法;
可通過 this.getClass().getClassLoader()獲取類對(duì)應(yīng)的加載器
類的卸載:(清除對(duì)應(yīng)類的Class對(duì)象 和 類的二進(jìn)制數(shù)據(jù)結(jié)構(gòu))
由Java虛擬自帶的三個(gè)類加載器加載的類不能卸載;(虛擬機(jī)會(huì)始終引用這3個(gè)類加載器,類加載器中有一個(gè)集合,又會(huì)一直引用其加載的類的Class對(duì)象)
用戶自定義的類加載器加載的類可以被卸載;
整理自孫衛(wèi)琴《Java面象對(duì)象編程》
總結(jié)
以上是生活随笔為你收集整理的java 类加载生命周期_Java类的加载与生命周期的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android studio导入ecli
- 下一篇: python调用ansysworkben