类加载器基本概念:
类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。
1)类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例;
2)类加载器负责加载动态生成的java字节代码,并转换成java.lang.class类的一个实例;
基本上所有的类加载器都是 java.lang.ClassLoader 类的一个实例
java.lang.ClassLoader 类介绍 java.lang.ClassLoader 类的基本职责就是根据一个指定的类的名称,找到或者生成其对应class的字节代码,然后从这些字节代码
中定义出一个 Java 类,即 java.lang.Class 类的一个实例。除此之外,ClassLoader 还负责加载 Java 应用所需的资源,如图像文件和配置文件等
。
表 1. 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 类。 对于 表 1 中给出的方法,表示类名称的 name 参数的值是类的二进制名称。需要注意的是内部类的表示,如 com.example.Sample$1 和 com.example.Sample$Inner 等表示方式.
类加载器的树状组织结构
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 类的方式实现自己的类加载器,以满足一些特殊的需求。
-----------------------------------------------------------------------------------------------------------------------------------------------
while(classLoader!=null){ System.out.println(classLoader); classLoader = classLoader.getParent(); }
-----------------------------------------------------------------------------------------------------------------------------------------------
除了引导类加载器之外,所有的类加载器都有一个父类加载器。通过 表 1 中给出的 getParent()
方法可以得到。对于系统提供的类加载器来说,系统类加载器的父类加载器是扩展类加载器,而扩展类加载器的父类加载器是引导类加载器;对于开发人员编 写的类加载器来说,其父类加载器是加载此类加载器 Java 类的类加载器。因为类加载器 Java 类如同其它的 Java
类一样,也是要由类加载器来加载的。一般来说,开发人员编写的类加载器的父类加载器是系统类加载器。类加载器通过这种方式组织起来,形成树状结构。树的根节点就是引导类加载器。图 1 中给出了一个典型的类加载器树状组织结构示意图,其中的箭头指向的是父类加载器。
每个 Java 类都维护着一个指向定义它的类加载器的引用,通过 getClassLoader() 方法就可以获取到此引用。代码清单 1 中通过递归调用 getParent() 方法来输出全部的父类加载器。代码清单 1 的运行结果如 代码清单 2 所示。 清单 2. 演示类加载器的树状组织结构的运行结果 sun.misc.Launcher$AppClassLoader@9304b1 sun.misc.Launcher$ExtClassLoader@190d11 如 代码清单 2 所示,第一个输出的是 ClassLoaderTree 类的类加载器,即系统类加载器。它是 sun.misc.Launcher$AppClassLoader 类的实例;第二个输出的是扩展类加载器,是 sun.misc.Launcher$ExtClassLoader 类的实例。需要注意的是这里并没有输出引导类加载器,这是由于有些 JDK 的实现对于父类加载器是引导类加载器的情况,getParent() 方法返回 null。