通過定義兩個類載入器載入同一位元組碼檔案來證明Class例項為什麼不是全域性唯一的

1.將一個名為Demo(沒有後綴)的位元組碼檔案放在D盤根目錄

2.定義兩個類載入器

自定義ClassLoader三要素:

    1. 繼承自ClassLoader,重寫findClass()
    1. 獲取位元組碼二進位制流
    1. 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例項載入時才會保持唯一性