美文网首页
类加载器双亲委托机制

类加载器双亲委托机制

作者: 龙剑灵 | 来源:发表于2019-12-30 01:53 被阅读0次

    自定义类加载器 MyTest18

    public class MyTest18 extends ClassLoader{
    
      private String classLoaderName;
    
      private String path;
    
      private String feleExtension = ".class";
    
      public MyTest18(String classLoaderName) {
        super(); //将系统类加载器当做该类加载的父加载器
        this.classLoaderName = classLoaderName;
      }
    
      public MyTest18(ClassLoader parent, String classLoaderName) {
        super(parent);// 显示指定该类加载器父加载器
        this.classLoaderName = classLoaderName;
      }
      public void setPath(String path) {
        this.path = path;
      }
    
      @Override
      protected Class<?> findClass(String className) throws ClassNotFoundException {
        System.out.println("className: " + className);
        System.out.println("classLoaderName: " + this.classLoaderName);
    
        byte[] data = this.loadClassData(className);
        return this.defineClass(className, data, 0, data.length);
      }
    
      private byte[] loadClassData(String className){
        byte[] data = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
    
        System.out.println("loadClassData.222.........");
        try {
          className = className.replace(".", "\\");
          String fileName = this.path + className + this.feleExtension;
          System.out.println("fileName: " + fileName);
          is = new FileInputStream(new File(fileName));
          baos = new ByteArrayOutputStream();
          int ch = 0;
          while (-1 != (ch = is.read())) {
            baos.write(ch);
          }
          data = baos.toByteArray();
        } catch (Exception e) {
    
        }finally {
          try {
            is.close();
            baos.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
        return data;
      }
    
    public static void main(String[] args) throws Exception {
    
        MyTest17 myTest = new MyTest17("loader17");
        //myTest.setPath("E:\\gitSpace\\jdk8\\out\\production\\classes\\");
        myTest.setPath("c:\\");
    
        Class<?> clazz = myTest.loadClass("jvm.classloader.MyTest2");
        System.out.println("class: " + clazz);
        System.out.println("class.hashCode: " + clazz.hashCode());
        Object object = clazz.newInstance();
        System.out.println(object);
        System.out.println("--------------------------------");
    
        MyTest17 myTest2 = new MyTest17("loader177");
        //myTest.setPath("E:\\gitSpace\\jdk8\\out\\production\\classes\\");
        myTest2.setPath("c:\\");
    
        Class<?> clazz2 = myTest2.loadClass("jvm.classloader.MyTest2");
        System.out.println("class2: " + clazz2);
        System.out.println("class2.hashCode: " + clazz2.hashCode());
        Object object2 = clazz2.newInstance();
        System.out.println(object2);
      }
    
    本例中,2个类加载器,都委托系统(或应用)加载器去加载,因此重写的findClass不会执行,没输出,在类路径上能找到,只会执行一次加载, hashCode是一致的

    class: class jvm.classloader.MyTest2
    class.hashCode: 366712642
    jvm.classloader.MyTest2@6d06d69c


    class2: class jvm.classloader.MyTest2
    class2.hashCode: 366712642
    jvm.classloader.MyTest2@7852e922

    若将类路径下的MyTest2.class删除后则输出如下
    每个类加载器都有自己的命名空间,命名空间由该加载器及所有父加载器所加载的类组成

    className: jvm.classloader.MyTest2
    classLoaderName: loader17
    loadClassData..........
    fileName: c:\jvm\classloader\MyTest2.class
    class: class jvm.classloader.MyTest2
    class.hashCode: 135721597
    jvm.classloader.MyTest2@87aac27


    className: jvm.classloader.MyTest2
    classLoaderName: loader177
    loadClassData..........
    fileName: c:\jvm\classloader\MyTest2.class
    class2: class jvm.classloader.MyTest2
    class2.hashCode: 1406718218
    jvm.classloader.MyTest2@e9e54c2

    public static void main(String[] args) throws Exception {
    
        MyTest18 myTest = new MyTest18("loader18");
        //myTest.setPath("E:\\gitSpace\\jdk8\\out\\production\\classes\\");
        myTest.setPath("c:\\");
    
        Class<?> clazz = myTest.loadClass("jvm.classloader.MyTest2");
        System.out.println("class: " + clazz);
        System.out.println("class.hashCode: " + clazz.hashCode());
        Object object = clazz.newInstance();
        System.out.println(object);
        System.out.println("--------------------------------");
    
        MyTest18 myTest2 = new MyTest18(myTest, "loader18");
        //myTest.setPath("E:\\gitSpace\\jdk8\\out\\production\\classes\\");
        myTest2.setPath("c:\\");
    
        Class<?> clazz2 = myTest2.loadClass("jvm.classloader.MyTest2");
        System.out.println("class2: " + clazz2);
        System.out.println("class2.hashCode: " + clazz2.hashCode());
        Object object2 = clazz2.newInstance();
        System.out.println(object2);
    
        System.out.println("--------------------------------");
    
        MyTest18 myTest3 = new MyTest18(myTest2, "loader19");
        //myTest.setPath("E:\\gitSpace\\jdk8\\out\\production\\classes\\");
        myTest3.setPath("c:\\");
    
        Class<?> clazz3 = myTest3.loadClass("jvm.classloader.MyTest2");
        System.out.println("class3: " + clazz3);
        System.out.println("class3.hashCode: " + clazz3.hashCode());
        Object object3 = clazz3.newInstance();
        System.out.println(object3);
      }
    
    此示例没删除MyTest2.class则输出如下
    第2个加载器加载的是父类的,第3个加载时,在1中已经加载过,所以3者是加载的同个类

    className: jvm.classloader.MyTest2
    classLoaderName: loader18
    loadClassData.222.........
    fileName: c:\jvm\classloader\MyTest2.class
    class: class jvm.classloader.MyTest2
    class.hashCode: 135721597
    jvm.classloader.MyTest2@87aac27


    class2: class jvm.classloader.MyTest2
    class2.hashCode: 135721597
    jvm.classloader.MyTest2@3e3abc88


    class3: class jvm.classloader.MyTest2
    class3.hashCode: 135721597
    jvm.classloader.MyTest2@6ce253f1

    相关文章

      网友评论

          本文标题:类加载器双亲委托机制

          本文链接:https://www.haomeiwen.com/subject/nnguoctx.html