zoukankan      html  css  js  c++  java
  • 自定义类加载器(二)

    示例代码(自定义类加载器)

    
    public class MyClassLoader extends ClassLoader {
    
        private String path="C:/Users/Administrator/Desktop/home/luciel/";    //默认加载路径
    
        private String name;                    //类加载器名称
    
        private final String  filetype=".class"; //文件类型
    
        /**
         * 这个构造方法中去调用ClassLoader无参构造方法从ClassLoader源码中可以得出:
         * 调用此构造方法会让系统类加载器成为该类加载器的父加载器。
         * @param name
         */
        public MyClassLoader(String name) {
            // TODO Auto-generated constructor stub
            super();
            this.name=name;
        }
    
        public MyClassLoader(ClassLoader parent,String name){
            super(parent);
            this.name=name;
        }
    
        @Override
        public Class<?> findClass(String name) throws ClassNotFoundException {
            // TODO Auto-generated method stub
            byte[] b=loadClassData(name);
            return defineClass(name, b, 0, b.length);
        }
    
        private byte[] loadClassData(String name) {
            byte[] data=null;
            InputStream in=null;
            name=name.replace('.', '/');
            ByteArrayOutputStream out=new ByteArrayOutputStream();
            try {
                in=new FileInputStream(new File(path+name+filetype));
                int len=0;
                while(-1!=(len=in.read())){
                    out.write(len);
                }
                data=out.toByteArray();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                try {
                    in.close();
                    out.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return data;
        }
    
        public String getPath() {
            return path;
        }
    
        public void setPath(String path) {
            this.path = path;
        }
    
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return this.name;
        }
    }
    
    public class Color {
       public Color() {
          System.out.println("Color is loaded by "+ this.getClass().getClassLoader());
       }
    }
    public class Red extends Color {
       public Red() {
          System.out.println("Red is loaded by "+ this.getClass().getClassLoader());
       }
    }
    public class TestMyClassLoader {
    
       public static void main(String[] args) throws Exception {
    
          MyClassLoader loader1 = new MyClassLoader("loader1");
          loader1.setPath("C:/Users/Administrator/Desktop/home/luciel/test1/");
    
          MyClassLoader loader2 = new MyClassLoader(loader1, "loader2");
          loader2.setPath("C:/Users/Administrator/Desktop/home/luciel/test2/");
    
          MyClassLoader loader3 = new MyClassLoader(null, "loader3");
          loader3.setPath("C:/Users/Administrator/Desktop/home/luciel/test3/");
    
          loadClassByMyClassLoader("com.demo.tcp.kaka.Red", loader2);
          loadClassByMyClassLoader("com.demo.tcp.kaka.Red",loader3);
       }
    
       private static void loadClassByMyClassLoader(String name, ClassLoader loader) throws Exception {
    
          Class<?> c = loader.loadClass(name);
          Object obj = c.newInstance();
       }
    }
    

    测试结果

    Color is loaded by loader1
    Red is loaded by loader1
    Color is loaded by loader3
    Red is loaded by loader3
    

    注意事项

    • 按照main方法中给三个类加载器传入的路径创建相应的环境,并将Red、Color的class类拷贝到home/luciel/test1/和home/luciel/test2/以及home/luciel/test3/目录中,将TestMyClassLoader类和MyClassLoader拷贝home/luciel/main/ 中,并在该目录下执行java 包名.TestMyClassLoader

    结果分析

    • 1、loadClassByMyClassLoader("Red",loader2);如测试代码中 我们调用了loader2去加载Red类但Red类却打印出由loader1加载,这是由于类加载器秉承的是父委托机制loader2在创建时包装了loader1为其父类加载器,而loader1创建时由于调用的是没有传入父类加载器的构造方法,因此它的父加载器为系统类加载器。因此几个加载器的关系如下:

      image
      由于loader1的路径下有Red类class文件所以loader1可以加载,因此载Red类构造方法中打印的类加载器为loader1.
      我门看似只去加载了Red类但运行结果却将Color父类加载了,而且Color类的加载在Red类之前,那是由于Red类主动使用 了Color类,因此在初始化Red类之前必须先初始化Color类,要初始化就必须先加载,所以先打印出了Color类的输出信息。

    • 2、loadClassByMyClassLoader("com.Red",loader3);再分析第二个测试代码,由于loader3创建时传入的父类加载器为 null,null表示根类加载器,那么loader3的父类加载器就是根类加载器,而根类加载器只会去加载那些系统核心类库,显然我们的Red和Color类不属于此范围,而就只能让loader3加载,loader3的加载路径下有这两个类对应的字节码因此可以成功加载,所以Red和Color类的类加载器为loader3。

      image

  • 相关阅读:
    Windows netsh命令的使用
    源码安装 qemu-2.0.0 及其依赖 glib-2.12.12
    .ko文件
    Suse环境下编译linux-2.6.24内核
    cut
    POJ3648 Wedding
    [Hnoi2010]Planar
    [中山市选2011]杀人游戏
    BZOJ3033 太鼓达人
    POJ1041 John's trip
  • 原文地址:https://www.cnblogs.com/kaka-qiqi/p/14527205.html
Copyright © 2011-2022 走看看