自定义类加载器

  1. 流程

    1. 继承ClassLoader类;
    2. 检查请求的类型是否已经被这个类加载器装载到命名空间了,如果已经装载直接返回;
    3. 委派类加载请求给父类加载器,如果父类加载器能够完成,则返回父类加载器加载的Class实例;
    4. 调用本类加载器的findClass()方法,获取对象字节码,获取到调用defineClass()导入类型到方法区;获取不到或其他原因导致失败,返回异常给loadClass(),再转抛异常,终止加载。
      说明:两个类加载器加载相同的类,JVM认为是不同的类。
  2. 代码实现
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.InputStream;

    /**

    • 自定义类加载器

    • /
      public class FileSystemClassLoader extends ClassLoader{
      private String root; // 类路径

      public FileSystemClassLoader(String root){

        this.root = root;

      }

      /**

      • Finds the class with the specified binary name.

      • This method should be overridden by class loader implementations that

      • follow the delegation model for loading classes, and will be invoked by

      • the {@link #loadClass <tt>loadClass</tt>} method after checking the

      • parent class loader for the requested class. The default implementation

      • throws a <tt>ClassNotFoundException</tt>.

      • @param name The binary name of the class

      • @return The resulting <tt>Class</tt> object

      • @throws ClassNotFoundException If the class could not be found

      • @since 1.2

      • /
        @Override
        protected Class findClass(String name) throws ClassNotFoundException { Class c = findLoadedClass(name); // 查找对应name的Class

        if (c != null){ // 找到直接返回

          return c;

        } else{

          ClassLoader parent = this.getParent();
          try {
              c = parent.loadClass(name); // 委派给父类
          } catch (ClassNotFoundException e) {
              e.printStackTrace();
          }
        
          if (c != null){
              return c;
          } else{
              byte[] classData = getClassData(name); // 返回字节数据
              if (classData != null){
                  c = defineClass(name,classData,0,classData.length);
              } else{
                  throw new ClassNotFoundException();
              }
          }

        }
        // return super.findClass(name);
        return c;

        }

        private byte[] getClassData(String classname){
        String path = root+"/"+classname.replace('.','/')+".class";

        // 将流中的数据转成字节数组
        try(InputStream is = new FileInputStream(path); ByteArrayOutputStream baos = new ByteArrayOutputStream();) {

          byte[] buffer = new byte[1024];
          int temp = 0;
          while((temp=is.read(buffer))!=-1){ // 读取数据并写入
              baos.write(buffer,0,temp);
          }
          return baos.toByteArray();

        } catch (Exception e){

          e.printStackTrace();
          return null;

        }
        }
        }

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务