類加載
類加載器(ClassLoader)
什麼是類加載器?
就是Java代碼在運作,JVM在啓動時,把類模板加載到內存去的工具
首先,一個Java程序真正的執行過程應該是你去調用了Java這個命令,然後程序開始執行,而執行的過程中,JVM會將很多類(.class文件,或者.jar文件)加載到當前的程序內存當中。
當你去寫 類型 a = new 類型()
時,類加載器就會把加載好的模板放到堆中申請空間並佔用空間,把東西加載到內存中。
類加載器的分類
真正獲得類模板的過程,是通過一個叫做ClassLoader的工具來獲得到的
作用:ClassLoader就是將一個存在於系統文件中的.class文件,加載到當前程序的內存當中,變成JVM中的一個對象、一個類模板,Java語言就可以識別這個Class類型
把類模板加載到工程中
問題:現有一個類的對象和他的.class文件,需要加載出這個類,生成一個對象。
defineClass()
:把這二進制文件變成我們想要的Class文件
首先自定義一個類加載器,返回的就是由Cent.class文件生成的類模板
public class MyClassLoader extends ClassLoader {
/*
//把從外部看到的.class文件變成內存中,在代碼中看到的Class文件(類模板),並且用這個Class來創建對象,這個.class文件在哪不用關心
defineClass()//第二個參數數組存放的就是.class文件轉換成的二進制碼的數組,可以把這二進制文件變成我們想要的Class文件
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
//找到那個.class文件,用文件流懟到這個文件上
FileInputStream fis = null;
try {
fis = new FileInputStream("Z:/Cent.class");
byte[] b = new byte[fis.available()];
fis.read(b);
return defineClass(name,b,0,b.length);//defindClass就是定義class的,是ClassLoader給出的
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return super.findClass(name);
}
}
ObjectInputStream使用了自己的類加載器(應用加載器),並不能加載出我們想要加載的那個類現在需要ObjectInputStream在加載我們的類時使用我們自定義的類加載器,加載其他類時使用自己的類加載器這時就需要繼承ObjectInputStream,重寫他的resolveClass方法了
重寫ObjectInputStream的類加載器
public class MyObjectInputStream extends ObjectInputStream {
private ClassLoader classLoader;
public MyObjectInputStream(InputStream in) throws IOException {
super(in);
}
public MyObjectInputStream(InputStream in, ClassLoader classLoader) throws IOException {
super(in);
this.classLoader = classLoader;
}
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
//如果可以創建對象成功就用的自己的類加載器,如果不成功,就捕獲異常,用父類的類加載器創建對象
try {
return Class.forName("baidu.ali.tencent.Cent",false,this.classLoader);//第二個參數initialize:說明這個類是否必須初始化。
/*
//當然這裏除了上面那樣寫,也可以像下面這樣寫,這是下面這樣的寫法具有侷限性,讓MyObjectInputStream類加載器只能加載這一種外部的類,不能加載其他類型的外部類
MyClassLoader loader = new MyClassLoader();
Class aClass = loader.loadClass("baidu.ali.tencent.Cent");
return aClass;
*/
} catch (Exception e) {
return super.resolveClass(desc);
}
}
}
ublic class HomeworkDemo {
public static void main(String[] args) {
MyClassLoader loader = new MyClassLoader();
try {
Class clazz = loader.loadClass("baidu.ali.tencent.Cent");//用自己定義的類加載器拿到了類模板了,加載的只是一個類型,還並不是對象
/*
ObjectInputStream使用了自己的類加載器(應用加載器),他只能加載寫在工程裏的類,並不能加載出我們想要加載的那個類
現在需要ObjectInputStream在加載我們的類時使用我們自定義的類加載器,加載其他類時使用自己的類加載器
這時就需要繼承ObjectInputStream,重寫他的resolveClass方法了
*/
ObjectInputStream ois = new MyObjectInputStream(new FileInputStream("Z:/object.lgc"),loader);//用loader把類型加載出來
Object object = ois.readObject();//成功的將外部我們想要加載的類加載進來了,生成了object對象
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}