8.類的加載、連接、初始化:
加載:將.class文件讀入到內存,併爲之創建一個java.lang.Class對象。一旦某個類被載入JVM中,同一個類就不會再被載入。在JAVA中,一個類用其全限定類名作爲標識,這裏指的全限定類名包括包名和類名。但在JVM中一個類用其全限定類名和一個加載類ClassLoader的實例ID作爲唯一標識(命名空間)。如:包pg下的Person類MyClassLoader的實例a加載,在JVM中表示爲(Person、pg、a)。
連接:把已讀入虛擬機的二進制Java類數據合併到虛擬機的運行時狀態中去。
分爲三步:.驗證:加成被夾在的類是否有正確的內部結構,並和其他類協調一致。.
準備.:爲類的靜態屬性分配內存,並設置默認初始值。
解析:將類的二進制數據中的符號引用替換成直接引用。
初始化:主要是對靜態屬性進行初始化,包括兩種方式:聲明靜態屬性時指定初始值、使用
靜態代碼塊初始化靜態屬性。
初始化時機:創建類的實例、調用某個類的靜態方法、調用某個類的靜態屬性或爲靜態屬性賦值、用Class.forName("類名")的方式加載類、初始化某個類的子類。通過類名.class方式加載某個類時,不會靜態初始化。
9.Java虛擬機中可以安裝多個類加載器,系統默認三個主要類加載器,每個類負責加載特定位置的類:BootStrap,ExtClassLoader,AppClassLoader。類加載器也是Java類,因爲其他是java類的類加載器本身也要被類加載器加載,顯然必須有第一個類加載器不是不是java類,這正是BootStrap。得到類加載器示例:
ClassLoader loader = ClassLoaderTest.class.getClassLoader();
//打印出當前的類加載器,及該類裝載器的各級父類加載器
while(loader != null){
System.out.println(loader.getClass().getName());
loader = loader.getParent();
}
19.類加載器之間的父子關係和管轄範圍圖
10.類加載器的委託機制:
當Java虛擬機要加載一個類時,到底派出哪個類加載器去加載呢?
首先當前線程的類加載器去加載線程中的第一個類。
如果類A中引用了類B,Java虛擬機將使用加載類A的類裝載器來加載類B。
還可以直接調用ClassLoader.loadClass(String name)方法(name字符串沒有.class後綴)來
指定某個類加載器去加載某個類。
每個類加載器加載類時,又先委託給其上級類加載器。
當所有祖宗類加載器沒有加載到類,回到發起者類加載器,還加載不了,則拋
ClassNotFoundException,不是再去找發起者類加載器的兒子,因爲沒有getChild方法,
即使有,那有多個兒子,找哪一個呢?
每個ClassLoader本身只能分別加載特定位置和目錄中的類,但它們可以委託其他的類裝載器去加載類,這就是類加載器的委託模式。類裝載器一級級委託到BootStrap類加載器,當BootStrap無法加載當前所要加載的類時,然後才一級級回退到子孫類裝載器去進行真正的加載。當回退到最初的類裝載器時,如果它自己也不能完成類的裝載,那就應報告ClassNotFoundException異常。
11.自定義類加載器加載類:
被加載類:
package myclassloadertest;//結合(1)想想此處爲什麼要繼承
public class BeLoadedClass extends MyClassLoaderTest{}
類加載器:
package myclassloadertest;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
public class MyClassLoader extends ClassLoader {
String classDir;
public MyClassLoader(String classDir) {
this.classDir=classDir;
}
@SuppressWarnings("deprecation")
@Override
protected Class<?> findClass(String className) {
String classPath=classDir+"\\"+className+".class";
ByteArrayOutputStream bao=null;
InputStream fis=null;
try {
fis=new FileInputStream(classPath);
bao=new ByteArrayOutputStream();
int hasRead=-1;
while((hasRead=fis.read())!=-1){
bao.write(hasRead);
bao.flush();
}
fis.close();
bao.close();
} catch (Exception e) {
e.printStackTrace();
}
byte buffer[]=bao.toByteArray();
return this.defineClass( buffer, 0, buffer.length);
}
}
類加載器測試:
package myclassloadertest;
public class MyClassLoaderTest {
public static void main(String[] args) throws Exception {
Class<?> myLoader=new
MyClassLoader("bin\\myclassloadertest").
loadClass("BeLoadedClass");
MyClassLoaderTest clazz=(MyClassLoaderTest) //(1)
myLoader.newInstance();
System.out.println(clazz.getClass().getClassLoader()
.getClass().getName());
}
}
輸出:myclassloadertest.MyClassLoader
---------------------- android培訓、java培訓、期待與您交流! ----------------------