通过定义两个类加载器加载同一字节码文件来证明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) ;ByteArrayOutp56cutStream 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:1735600054pkg.custom.ad8MyClassLoader2@7f31245a|hashcode:325040804
可以看出由两个不同的类加载器加载,两者的哈希值不同,即所得到的类对象是不同的。
结论:
- 同一个Class被不同的类加载器加载后在JVM中产生的类对象是不同的
- 在同一个类加载器作用范围内Class实例加载时才会保持唯一性