Java类加载器

来源:互联网 发布:vs 编程入门视频教程 编辑:程序博客网 时间:2024/06/14 10:46


类加载器(class loader)是用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。

基本上所有的类加载器都是 java.lang.ClassLoader类的一个实例。下面详细介绍这个 Java 类。

java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个 Java 类,即 java.lang.Class类的一个实例。

ClassLoader提供了一系列的方法,比较重要的方法如:

方法说明getParent()返回该类加载器的父类加载器。loadClass(String name)加载名称为 name的类,返回的结果是 java.lang.Class类的实例。findClass(String name)查找名称为 name的类,返回的结果是 java.lang.Class类的实例。findLoadedClass(String name)查找名称为 name的已经被加载过的类,返回的结果是 java.lang.Class类的实例。defineClass(String name, byte[] b, int off, int len)把字节数组 b中的内容转换成 Java 类,返回的结果是 java.lang.Class类的实例。这个方法被声明为 final的。resolveClass(Class<?> c)链接指定的 Java 类。

java虚拟机中可以安装多个类加载器,系统默认三个主要的类加载器,每个加载器负责加载特定位置的类。
系统默认的三个类加载器之间的父子关系:BootStrap(爷)------ExtClassLoader(父)-----AppClassLoader(子)
注意:类加载器也是java类,但是这些加载器类本身又由谁来加载呢?显然必须有第一个类加载器不是java类,
这个加载器就是BootStrap,它不是一个java类,是直接在虚拟机里面的一个加载器。其他两个加载器都是java类。

BootStrap加载JRE/lib/rt.jar里面的类,ExtClassLoader加载JRE/lib/ext/*.jar里面的类,AppClassLoader加载classpath指定的所有jar或目录里面的类。

第一个类加载器用来加载存储在文件系统上的 Java 字节代码。完整的实现如下

  1. public class FileSystemClassLoader extends ClassLoader { 

  2.     private String rootDir; 

  3.     public FileSystemClassLoader(String rootDir) { 
  4.         this.rootDir = rootDir; 
  5.     } 

  6.     protected Class<?> findClass(String name) throws ClassNotFoundException { 
  7.         byte[] classData = getClassData(name); 
  8.         if (classData == null) { 
  9.             throw new ClassNotFoundException(); 
  10.         } 
  11.         else { 
  12.             return defineClass(name, classData, 0, classData.length); 
  13.         } 
  14.     } 

  15.     private byte[] getClassData(String className) { 
  16.         String path = classNameToPath(className); 
  17.         try { 
  18.             InputStream ins = new FileInputStream(path); 
  19.             ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
  20.             int bufferSize = 4096; 
  21.             byte[] buffer = new byte[bufferSize]; 
  22.             int bytesNumRead = 0; 
  23.             while ((bytesNumRead = ins.read(buffer)) != -1) { 
  24.                 baos.write(buffer, 0, bytesNumRead); 
  25.             } 
  26.             return baos.toByteArray(); 
  27.         } catch (IOException e) { 
  28.             e.printStackTrace(); 
  29.         } 
  30.         return null; 
  31.     } 

  32.     private String classNameToPath(String className) { 
  33.         return rootDir + File.separatorChar 
  34.                 + className.replace('.', File.separatorChar) + ".class"; 
  35.     } 
  36.  }
好了,就先写到这里吧,后续有新的观点再添加!



0 0
原创粉丝点击