JVM类加载器(二)

类加载器负责加载Java类的字节代码到Java虚拟机中,可以根据指定的类名(如java.lang.Object)来装载class文件的内容到Runtime Data Area中的Method Area(方法区域)。Java程序员可以extends java.lang.ClassLoader类来写自己的Class loader

类加载器的模型

类加载器双亲委派模型

如果一个类加载器接收到了类加载的请求,它首先把这个请求委托给他的父类加载器去完成,每个层次的类加载器都是如此,因此所有的加载请求都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它在搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

双亲委派模型的优点

Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在tools.jar中,无论哪个类加载器要加载这个类,最终都会委派给启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果用户自己写了一个名为java.lang.Object的类,并放在程序的Classpath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也无法保证,应用程序也会变得一片混乱。

类加载器的类型

站在JVM的角度讲,主要有两种类型加载器:启动类加载器和其它的类加载器。启动类加载器是JVM实现的一部分,使用C++语言实现,其它类加载器都由Java语言实现 ,独立于虚拟机外部,并且全部继承抽象类java.lang.ClassLoader

Bootstrap ClassLoader 启动类加载器

这是JVM的根ClassLoader,它是用C++实现的,JVM启动时初始化此ClassLoader,并由此ClassLoader完成$JAVA_HOME$jre\lib\rt.jar(Sun JDK的实现)中所有class文件的加载,这个jar中包含了Java规范定义的所有接口以及实现(加载可信的类,包括Java的API)。启动类加载器无法被Java程序直接引用,Java程序在它开始运行之前并非被完全加载,其各个部分是在必需时才加载。

Extension ClassLoader 扩展类加载器

扩展类加载器负责加载<JAVA_HOME>\lib\ext目录中或者java.ext.dirs系统变量所指定的所有类库,开发者可以直接使用扩展类加载器。

Application ClassLoader 应用程序类加载器

JVM用此classloader来加载用户类路径 (Classpath)上所指定的类库,包含指定的jar包以及目录,该加载器有时也称为系统类加载器。开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

User-Defined ClassLoader 用户自定义类加载器

User-DefinedClassLoader是Java开发人员继承ClassLoader抽象类自行实现的ClassLoader,基于自定义的ClassLoader可用于加载非Classpath中的jar以及目录。

类的加载的过程


类的加载过程:加载,链接,初始化。

加载

加载过程负责找到二进制字节码并加载至JVM中,JVM通过类名、类所在的包名通过ClassLoader来完成类的加载。

连接

链接过程负责对二进制字节码的格式进行校验、初始化装载类中的静态变量以及解析类中调用的接口、类。

验证

确保被导入类的正确性。

准备

为类变量分配内存,并将其初始化为默认值。

解析

解析这个类创建的对其他类的所有引用。

初始化

初始化过程即为有父类的情况,对父类初始化,或者执行类中的静态初始化代码、构造器代码以及静态属性的初始化,在四种情况下初始化过程会被触发执行:调用new;反射调用类中的方法;子类调用了初始化;JVM启动过程中指定的初始化类。
所有的类都是在对其第一次使用时候,动态加载到JVM中。当程序创建第一个对类的静态成员引用时,就会加载这个类。这个证明构造方法也是静态方法,即使构造方法没有static关键字。因此new操作符创建类的新对象也会被当做对类的静态成员的引用。

# JVM, Java

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×