java类加载器
1、什么是类加载器?类加载器实现什么功能?
类加载器(Class Loader)是用来加载java类到java虚拟机(JVM)中,加载步骤:
- java编译器编译java源文件(*.java文件)成字节码(*.class)文件
- 类加载器负责读取java字节码文件,并转换成java.lang.Class类的一个实例,每个实例代表一个java类
- 通过该实例的newInstance方法,就可以获取该类的一个对象
java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个 Java 类,即 java.lang.Class类的一个实例。
2、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的。
3、类加载器的树状组织结构
Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。系统提供的类加载器主要有下面三个:
- 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自java.lang.ClassLoader。
- 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
- 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。
除了系统提供的类加载器以外,开发人员可以通过继承 java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需求。
除了引导类加载器之外,所有的类加载器都有一个父类加载器。通过 上面表中给出的 getParent()方法可以得到。对于系统提供的类加载器来说,系统类加载器的父类加载器是扩展类加载器,而扩展类加载器的父类加载器是引导类加载器;对于开发人员编写的类加载器来说,其父类加载器是加载此类加载器 Java 类的类加载器。因为类加载器 Java 类如同其它的 Java 类一样,也是要由类加载器来加载的。一般来说,开发人员编写的类加载器的父类加载器是系统类加载器。类加载器通过这种方式组织起来,形成树状结构。树的根节点就是引导类加载器。下图中给出了一个典型的类加载器树状组织结构示意图,其中的箭头指向的是父类加载器。
开发自己的类加载器
虽然在绝大多数情况下,系统默认提供的类加载器实现已经可以满足需求。但是在某些情况下,您还是需要为应用开发出自己的类加载器。比如您的应用通过网络来传输 Java 类的字节代码,为了保证安全性,这些字节代码经过了加密处理。这个时候您就需要自己的类加载器来从某个网络地址上读取加密后的字节代码,接着进行解密和验证,最后定义出要在 Java 虚拟机中运行的类来。下面将通过两个具体的实例来说明类加载器的开发。
文件系统类加载器
第一个类加载器用来加载存储在文件系统上的 Java 字节代码
1 public class FileSystemClassLoader extends ClassLoader { 2 3 private String rootDir; 4 5 public FileSystemClassLoader(String rootDir) { 6 this.rootDir = rootDir; 7 } 8 9 protected Class<?> findClass(String name) throws ClassNotFoundException { 10 byte[] classData = getClassData(name); 11 if (classData == null) { 12 throw new ClassNotFoundException(); 13 } 14 else { 15 return defineClass(name, classData, 0, classData.length); 16 } 17 } 18 19 private byte[] getClassData(String className) { 20 String path = classNameToPath(className); 21 try { 22 InputStream ins = new FileInputStream(path); 23 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 24 int bufferSize = 4096; 25 byte[] buffer = new byte[bufferSize]; 26 int bytesNumRead = 0; 27 while ((bytesNumRead = ins.read(buffer)) != -1) { 28 baos.write(buffer, 0, bytesNumRead); 29 } 30 return baos.toByteArray(); 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 return null; 35 } 36 37 private String classNameToPath(String className) { 38 return rootDir + File.separatorChar 39 + className.replace('.', File.separatorChar) + ".class"; 40 } 41 }
http://blog.csdn.net/xgdofull/article/details/5624777