java类加载

来源:互联网 发布:苹果手机电池修复软件 编辑:程序博客网 时间:2024/04/25 20:57
Java源程序在编译后生成Class类文件,在类文件中存储的各种信息最终都需要加载到虚拟机中之后才能被运行和使用。

虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转化解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。



加载 加载是类加载过程的第一个阶段,在这个阶段,虚拟机需要完成的功能主要有:(1)通过一个类的权限定名来获取定义该类的二进制字节流(2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构(3)在Java堆中生成一个代表该类的java.lang.Class对象,作为方法区这些数据的访问入口。

验证(很重要但不是一定必要的阶段)验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
比如说这个类是否有父类(Object就没有父类)
比如说这个类是否继承了不该继承的父类(final类不可以继承)
也就是检查java语法,保证不存在不符合java语法的数据。


准备 准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。所谓类变量,就是被static关键字修饰的变量,不包括实例变量。给静态变量赋0值。
Static Int value=32;
则给Value赋值为0.

解析 解析阶段是虚拟机将常量池内中的符号引用替换为直接引用的过程。

符号引用:它是一个字符串。它给出了被引用的内容的名字并且可能会包含一些其他关于这个被引用项的信息--这些信息必须唯一地识别一个类、字段、方法。这样,对于其他类的符号引用必须给出类的全名。对于其他类的字段,必须给出类名、字段名、字段描述符。对于其他类的方法的引用必须给出类名、方法名以及方法描述符。

直接引用:对于指向“类型”【Class对象】、类变量、类方法的直接引用可能是指向方法区的本地指针。

符号引用和虚拟机的内存布局无关,符号引用的目标不一定加载到内存上了。
直接引用和虚拟机的内存布局有关,所以直接引用的目标一定加载到内存中。
符号引用在不同的虚拟机上被翻译出来的直接引用不同。

初始化 类初始化阶段是类加载过程的最后一步,到了这一阶段,才真正开始执行类中定义的Java程序代码。
Static int value = 32;
则给value赋值为32.

初始化的条件:
有且只有五种
New,调用静态字段(final,因为常量池的原因,没有调用定义final的类,不会初始化),
调用静态方法,通过反射调用的类,包含main的类,父类还没有初始化,则先初始化父类。


类加载器

类加载过程的第一个阶段是加载,它主要是根据类的权限定名来获取类的二进制字节流。这个阶段主要是通过类加载其完成的。

绝大部分Java程序都会使用到三种类加载器:启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)、和应用程序类加载器(Application ClassLoader),当然我们还可以使用自定义的类加载。




启动类加载器 启动类加载器是C++语言实现的,是虚拟机自身的一部分,它负责加载JRE/lib/tr.jar中的类,或者被-Xbootclasspath参数指定的路径中的能被虚拟机识别的类库。
扩展类加载器 有Java语言实现,负责加载Java平台中扩展功能的一些Jar包,包括jre/lib/ext/*.jar或者java.ext.dies系统变量指定目录下的jar包。
应用程序类加载器 一般也称为系统类加载器,它负责加载用户路径中指定的jar包及目录中class。
在上面的类加载器图中,我们可以看到类加载器中存在一种层次关系,这是类加载起的双亲委派模型(Parents Delegation Model)。
双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应该有自己的父类加载器。
这里类加载器间的父子关系不是通过继承来实现,而是使用组合关系来复用类加载器的代码。

双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。每个层次的类加载都是如此,因此所有的加载请求最终都应传送给顶层的启动类加载器中,只有父类加载器反馈自己无法完成这个请求时,子加载器才会尝试自己去加载。

双亲委派机制的意义在于,对于保证java程序的稳定运行很重要,比如类java.lang.Object,他存放在rt.jar之中,无论哪个类加载器要加载这个类,最终都是为派给启动类加载器去加载,因此Object类在程序的各种类加载环境中都是一个类。如果没有双亲委派模型,由各个类加载器自行去加载的话,如果用户自己写了一个java.lang.Object的类,并放在程序的ClassPath中,那么系统就会出现多个不同的Object类,很混乱。
原创粉丝点击