通過定義兩個類載入器載入同一位元組碼檔案來證明Class例項為什麼不是全域性唯一的
1.將一個名為Demo(沒有後綴)的位元組碼檔案放在D盤根目錄
2.定義兩個類載入器
自定義ClassLoader三要素:
- 繼承自ClassLoader,重寫findClass()
- 獲取位元組碼二進位制流
- defineClass載入生成Class例項
package pkg.custom;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
/**
* 自定義ClassLoader三要素:
* 1. 繼承自ClassLoader,重寫findClass()
* 2. 獲取位元組碼二進位制流
* 3. defineClass載入生成Class例項
*/
public class MyClassLoader1 extends ClassLoader {
private final String CLASS_PATH = "d://Demo";
protected Class<?> findClass(String name) {
try {
//獲取位元組碼二進位制流
FileInputStream in = new FileInputStream(this.CLASS_PATH);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len = -1;
while ((len = in.read(buf)) != -1) {
baos.write(buf, 0, len);
}
in.close();
byte[] classBytes = baos.toByteArray();
//載入Class位元組碼
return defineClass(classBytes, 0, classBytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
//===========================================================
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
public class MyClassLoader2 extends ClassLoader {
private final String CLASS_PATH = "d://Demo" ;
protected Class<?> findClass(String name) {
try {
FileInputStream in = new FileInputStream(this.CLASS_PATH) ;
ByteArrayOutputStream baos = new ByteArrayOutputStream() ;
byte[] buf = new byte[1024] ;
int len = -1 ;
while((len = in.read(buf)) != -1){
baos.write(buf , 0 , len);
}
in.close();
byte[] classBytes = baos.toByteArray();
return defineClass( classBytes , 0 , classBytes.length) ;
} catch (Exception e) {
e.printStackTrace();
}
return null ;
}
}
3.Main函式
public class Application {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader c1 = new MyClassLoader1() ;
//利用自定義載入器1載入物件
//呼叫ClassLoader.loadClass()載入位元組碼會自動呼叫findClass方法
Class<?> clz1 = c1.loadClass("Demo");
System.out.println(clz1.getClassLoader() + "|hashcode:" + clz1.hashCode());
ClassLoader c2 = new MyClassLoader2() ;
//利用自定義載入器2載入物件
Class<?> clz2 = c2.loadClass("Demo");
System.out.println(clz2.getClassLoader() + "|hashcode:" + clz2.hashCode());
}
}
執行main,得到輸出結果:
pkg.custom.MyClassLoader1@74a14482|hashcode:1735600054
pkg.custom.MyClassLoader2@7f31245a|hashcode:325040804
可以看出由兩個不同的類載入器載入,兩者的雜湊值不同,即所得到的類物件是不同的。
結論:
- 同一個Class被不同的類載入器載入後在JVM中產生的類物件是不同的
- 在同一個類載入器作用範圍內Class例項載入時才會保持唯一性