Java ClassLoader 类加载器

来源:互联网 发布:百度搜索软件 编辑:程序博客网 时间:2024/04/26 15:22

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
      加载 就是指将class文件读入内存,并为之创建一个Class对象。 任何类被使用时系统都会建立一个Class对象。
      连接
           验证 是否有正确的内部结构,并和其他类协调一致
           准备 负责为类的静态成员分配内存,并设置默认初始化值(静态成员,类的创建而创建)
           解析 将类的二进制数据中的符号引用替换为直接引用
     初始化 就是我们以前讲过的初始化步骤



加载器

1. Bootstrap ClassLoader

负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类

2. Extension ClassLoader

负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包

3. App ClassLoader

负责记载classpath中指定的jar包及目录中class

4. Custom ClassLoader

属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader

加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。


类的初始化

    类什么时候才被初始化:

1)创建类的实例,也就是new一个对象

2)访问某个类或接口的静态变量,或者对该静态变量赋值

3)调用类的静态方法

4)反射(Class.forName("com.lyj.load"))

5)初始化一个类的子类(会首先初始化子类的父类)

6)JVM启动时标明的启动类,即文件名和类名相同的那个类

         只有这6中情况才会导致类的类的初始化。


自定义加载器

public class CustomClassLoader extends ClassLoader {      // 要加载的类      private String name;      // 设置父加载器和需要加载的类    public CustomClassLoader(ClassLoader parent , String name) {          super(parent);          if(name == null || name.length() <= 0)              throw new NullPointerException();          this.name = name;      }      // 重写加载器    @Override      protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {          Class<?> clazz = null;          /**如果是我们想要热加载的类则调用我们重写的findClass方法来加载**/          if(this.name.equals(name) && !"java".equals(name)){          // 调用系统加载class文件            clazz = findLoadedClass(name);              if(clazz == null)              // 调用自定义的                clazz = findClass(name);                // 类的生命周期包括:加载、验证、准备、解析、初始化、使用、卸载。其中验证、准备、解析统称为连接             //如果类已连接过,resolveClass方法会直接返回              if(resolve)                  resolveClass(clazz);            return clazz;          }          // 调用父加载器        return super.loadClass(name , resolve);      }        @Override      protected Class<?> findClass(String name) throws ClassNotFoundException {      // 获得实际存储class文件位置        String fileName = c2f(name);        // 读取class文件        byte[] bytes = f2b(fileName);          // 根据class文件生成Class类对象        return defineClass(name, bytes, 0, bytes.length);      }        // 类名转为文件名     private String c2f(String name){          /**编译后的class文件存放的目录**/          String baseDir = "F:\\classes";          name = name.replace("." , File.separator);          name = baseDir + name + ".class";          return name;      }        // 读取文件byte数组     private byte[] f2b(String fileName){          RandomAccessFile file = null;          FileChannel channel = null;          byte[] bytes = null;          try {              /**随机存取文件对象,只读取模式**/              file = new RandomAccessFile(fileName , "r");              /**NIO文件通道**/              channel = file.getChannel();              /**NIO字节缓冲**/              ByteBuffer buffer = ByteBuffer.allocate(1024);              int size = (int) channel.size();              bytes = new byte[size];              int index = 0;              /**从NIO文件通道读取数据**/              while (channel.read(buffer) > 0){                  /**字节缓冲从写模式转为读取模式**/                  buffer.flip();                  while (buffer.hasRemaining()){                      bytes[index] = buffer.get();                      ++index;                  }                  /**字节缓冲的readerIndex、writerIndex置零**/                  buffer.clear();              }          } catch (FileNotFoundException e) {              e.printStackTrace();          } catch (IOException e) {              e.printStackTrace();          }finally {              if (channel != null) {                  try {                      channel.close();                  } catch (IOException e) {                      e.printStackTrace();                  }              }              if (file != null) {                  try {                      file.close();                  } catch (IOException e) {                      e.printStackTrace();                  }              }          }          return bytes;      }        // 加载     public Class<?> loadClass(){          try {          // 调用系统loadClass(name,false)            return loadClass(name);          } catch (ClassNotFoundException e) {              e.printStackTrace();              return null;          }      }  }  


public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException {String name = "top.xfdtm.test.Person";CustomClassLoader loader = new CustomClassLoader(Thread.currentThread().getContextClassLoader(), name);Class<?> clazz = loader.loadClass();Object obj = clazz.newInstance();}




0 0
原创粉丝点击