知识回顾10、类装载器学习一、类加载器的基本概念
来源:互联网 发布:夜间灯光数据下载 编辑:程序博客网 时间:2024/06/03 21:03
类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一。它使得 Java 类可以被动态加载到 Java 虚拟机中并执行。类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的。Java Applet 需要从远程下载 Java 类文件到浏览器中并执行。现在类加载器在 Web 容器和 OSGi 中得到了广泛的使用。一般来说,Java 应用的开发人员不需要直接同类加载器进行交互。Java 虚拟机默认的行为就已经足够满足大多数情况的需求了。不过如果遇到了需要与类加载器进行交互的情况,而对类加载器的机制又不是很了解的话,就很容易花大量的时间去调试ClassNotFoundException
和NoClassDefFoundError
等异常。本文将详细介绍 Java 的类加载器,帮助读者深刻理解 Java 语言中的这个重要概念。下面首先介绍一些相关的基本概念。
类加载器基本概念
顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成java.lang.Class
类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的newInstance()
方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。
java.lang.ClassLoader类的介绍
java.lang.ClassLoader
类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个 Java 类,即java.lang.Class
类的一个实例。除此之外,ClassLoader
还负责加载 Java 应用所需的资源,如图像文件和配置文件等。不过本文只讨论其加载类的功能。为了完成加载类的这个职责,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 类。对于上表中给出的方法,表示类名称的name
参数的值是类的二进制名称。需要注意的是内部类的表示,如com.example.Sample$1
和com.example.Sample$Inner
等表示方式。这些方法会在下面介绍类加载器的工作机制时,做进一步的说明。下面介绍类加载器的树状组织结构。类加载器的树状组织结构
Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。系统提供的类加载器主要有下面三个:
- 引导类加载器(Bootstrap):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自
java.lang.ClassLoader
。 - 扩展类加载器(ExtClassLoader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
- 系统类加载器(AppClassLoader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过
ClassLoader.getSystemClassLoader()
来获取它。
除了系统提供的类加载器以外,开发人员可以通过继承 java.lang.ClassLoader
类的方式实现自己的类加载器,以满足一些特殊的需求。
除了引导类加载器之外,所有的类加载器都有一个父类加载器。通过上表中给出的 getParent()
方法可以得到。对于系统提供的类加载器来说,系统类加载器的父类加载器是扩展类加载器,而扩展类加载器的父类加载器是引导类加载器;对于开发人员编写的类加载器来说,其父类加载器是加载此类加载器 Java 类的类加载器。因为类加载器 Java 类如同其它的 Java 类一样,也是要由类加载器来加载的。一般来说,开发人员编写的类加载器的父类加载器是系统类加载器。类加载器通过这种方式组织起来,形成树状结构。树的根节点就是引导类加载器。下表中给出了一个典型的类加载器树状组织结构示意图,其中的箭头指向的是父类加载器。
下面代码清单一演示了类加载器的树状结构:
public class ClassLoaderTree { public static void main(String[] args) { ClassLoader loader = ClassLoaderTree.class.getClassLoader(); while (loader != null) { System.out.println(loader.getClass().getName()); loader = loader.getParent(); } System.out.println(loader);//最后当loader=null的时候。这个时候loader代表的是引导类加载器BootStrap } }
输出结果:
sun.misc.Launcher$AppClassLoadersun.misc.Launcher$ExtClassLoadernull
第一个输出的是
ClassLoaderTree
类的类加载器,即系统类加载器。它是 sun.misc.Launcher$AppClassLoader
类的实例;第二个输出的是扩展类加载器,是sun.misc.Launcher$ExtClassLoader
类的实例。需要注意的是这里并没有输出引导类加载器,这是由于有些 JDK 的实现对于父类加载器是引导类加载器的情况,getParent()
方法返回null
。- 知识回顾10、类装载器学习一、类加载器的基本概念
- 知识回顾12、类加载器学习三、类加载器的委托模式
- 知识回顾11、类加载器学习二、自定义类加载器
- 类装载器学习
- 类装载器学习
- 类装载器学习
- 类装载器学习
- 知识回顾(一)--类的封装
- 线程知识回顾(一)---基本概念
- 类装载器学习笔记
- Java类加载器学习1——类加载器的基本概念
- 传智播客Servlet学习,Tomcat中的类装载器对Servlet程序的装载机制
- C++ ”类“ 知识的回顾
- Java的类装载器
- Java 的类装载器
- 动态库的加载----程序装载器
- c#学习一:类的基本概念
- JAVA使用类装载器装载配置文件
- 项目描述:
- 黑马程序员-关于插入一条数据,马上得到该数据ID
- rabbitmq项目的worker_pool_sup学习
- rabbit_sup.erl源码文件学习
- 黑马程序员-005SQL语句锦集
- 知识回顾10、类装载器学习一、类加载器的基本概念
- 二元查找树转换为它的镜像
- 黑马程序员-文件IO操作
- Android测试教程(10):ActivityInstrumentationTestCase2示例
- IoAttachDevice;IoAttachDeviceToDeviceStack
- Android OpenGL ES 开发教程(10):绘制线段Line Segment
- Oracle培训的一些感受
- Android ApiDemos示例解析(8):App->Activity->Hello world
- Java Reflection 教程(2): Classes 类定义