黑马程序员训练营:类加载器

来源:互联网 发布:租号玩软件下载 编辑:程序博客网 时间:2024/05/15 11:10

一、类加载的详细过程

1、加载:将二进制数据写入内存,并在堆区创建能够映射方法区中相应类的方法的Class对象。

加载的方式:

(1)本地系统加载(注意加载的起始搜索路径)

(2)网络下载文件中加载

(3)zip,jar压缩文件等归档文件中加载

(4)从专有数据库中提取.class文件

(5)java源文件动态编译为.class文件

2、连接:就是将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中去。包括验证、准备、解析三个步骤。

(1)验证:类文件的结构检查、语义检查、字节码验证、二进制兼容性的验证。

(2)准备:为静态变量分配内存并置系统默认值。

(3)解析:将符号引用转换为直接引用。

3、初始化:为静态变量赋予初始值。初始化类仅在主动使用类的情况下执行。

主动使用主要包括:创建类的实例、访问类的静态成员、反射、初始化一个类的子类、启动类。

二、类加载器的层次结构及其工作原理

1、类加载器的作用

类加载器负责读取java字节码文件,并将其转换成java.lang.class类的一个实例。每个这样的实例都代表一个java类。通过此实例的newInstance()方法就可以创建一个该实例的对象。在程序中,可以通过classname.class的方式引用class的一个classname实例。

需要注意的是,java中的所有类都是class类的实例。

2、类加载器的分类

(1)引导类加载器:加载java核心库,用原生代码实现。

(2)扩展类加载器:加载java扩展库。Java虚拟机的实现会提供一个扩展库的目录,扩展类加载器会自动从此目录中查找并加载java类。

(3)系统类加载器:根据java应用定义的类路径(classpath)查找并加载java类。其父类为扩展类加载器。

(4)自定义加载器:由用户定义并且继承自ClassLoader类的加载器,其父类加载器一般为系统类加载器。

3、类加载器的父委托机制

(1)类加载的过程:当一个类加载器启动加载一个类时,首先将任务交由父加载器处理,而父对象按同样的方式进行工作。如果父加载器已经或能够完成就返回此类型,否则由子加载器处理。

(2)父子关系的理解:父子加载器并不一定是继承关系,而是包含关系。任一加载器都必须有且唯一的父加载器,所有的加载器都在树形结构中有自己的位置。引导类加载器的名字为null

(3)定义与初始类加载器概念:成功加载类的为定义加载器,从定义加载器开始到发起加载请求的加载器之间都是初始加载器。这个概念主要标识类加载器的加载记录。

(4)代理模式的作用:保护核心类库和对类的访问限制。

4、java类的加载方式

(1)隐式加载:当用需要并且用new关键字实例化一个对象时,系统将调用当前线程的类加载器加载一个类。

(2)显式加载:我们可以指定一个类加载器去加载一个类。有两种方式支持这么做。一种是用java.lang.class中的forName()方法,另一种是java.lang.classloader中的loadclass()方法。这两种方法都加载指定的类并且返回class类的一个实例。

三、自定义类加载器

1、类加载器的工作流程图

1)查看自己是否已经加载过该类,如果有,则返回该类;如果没有进入下一步。

2)如果有父加载器,让父加载器从第一步开始执行(递归)。如果没有,则自行加载。

3)如果不能加载,抛出ClassNotFoundException异常。如果不是初始发动加载请求的加载器,异常将被子加载器捕捉。

4)如果子加载器发现ClassNotFoundException,则自行加载。

5)最终,能加载,则进入下一步,否则抛出ClassNotFoundException异常。

6)检查resolve是否为真,如果为真,则进行连接操作。

7)返回类。

2、加载的实现过程说明

1)加载的入口函数为loadClass,已由系统实现。对于(1)(2)(3)(5)(6)(7)等常规步骤,也由系统给出。我们需要做的就是自行加载的模块。

2)自行加载模块的接口为findclass,主要完成将二进制数据载入内存并调用defineclass函数映射成class的实例的任务。

3findclass必须抛出ClassNotFoundException异常,以便在递归序列中被接过任务的子加载器捕捉。

4findclass不能由其他其他异常中断,否则递归序列无法继续到最后。

5)必须重载classloader的两个构造函数,以构成加载器父委托机制。

原创粉丝点击