java类加载详解

1,类的加载过程;

   
 JVM将看似加载过程分成三单步骤:装载(load),链接(link)和初始化(initialize),其中链接以分为三个步骤;

     验证(varification),准备(Preparation),和解析(Resolution);如下图

图片 1

   其实
类从让加载到虚拟机内存中开始,直到卸载出内存为止,它的所有生命周期包括了:加载、验证、准备、解析、初始化、使用与卸载这7个阶段。其中,证实、准备与剖析这三个部分统称为连续(linking)

   图片 2

 

 

  

里头,加载、验证、准备、初始化和卸载这五个阶段的相继是规定的,类的加载过程得以这种顺序按的“开始”(仅仅依靠的是始于,而不执行或者终止,因为这些号便都是相交叉的搅和进行,通常会以一个级实施之长河被调用或者激活另一个流),而解析阶段则非肯定(它当好几情况下好以初始化阶段后重新开,这是为着支持Java语言的运行时绑定。

    a:装载:装载 阶段 是相仿加载 的第一单等级,在此号虚拟机要
完成三宗业务

                 

     
 1、 通过一个近似的全限定名来取定义此类的次迈入制字节流,也即是找并加载类的二进制数据;。

     
 2、 将以此字节流所表示的静态存储结构转化为方法区的周转时数据结构。

     
 3、 在Java堆着变化一个表示是类似的java.lang.Class对象,作为方法区这些数据的走访入口。

       

      加载阶段就可以利用系统提供的类似加载器在做到,也得由用户从定义的类加载器来好。

     
加载阶段及连接等的片段内容(如一片字节码文件格式验证动作)是穿插进行的,加载阶段尚未形成,连接路可能已上马。

     JVM在内存 中之 表现形式:

图片 3

 

   b 验证:

     
验证是连续路的率先步,这无异品的目的是为保证Class文件之字节流中蕴含的音信相符当下虚拟机的渴求,并且不会见害虚拟机自身的安全。

   
 Java语言本身是对立安全的语言,使用Java编码是无能为力成功使访问数组边界外的多少、将一个靶转型为其并未实现之档次等,如果这么做了,

   
 编译器将拒绝编译。但是,Class文件并不一定是由Java源码编译而来,可以以其他途径,

   
 包括用十六进制编辑器(如UltraEdit)直接编写。如果一直编写了损害的“代码”(字节流),而虚拟机在加载该Class时未开展自我批评的话,就生或挫伤及虚拟机或程序的平安。

 

 
   不同之虚拟机,对近似证的实现可能截然不同,但大约都见面成功下面四独号的证实:

     图片 4

    c 准备:

     
 备阶段是为类的静态变量分配内存并将其初始化为默认值,这些内存都将以方法区中开展分红。

     
 准备等不分开配类中之实例变量的内存,实例变量将见面在靶实例化时趁对象同分配在Java堆着。

        public static int value=123;//在准备等value初始值为0
。在初始化阶段才会化123 。

    d 解析:

       解析阶段是虚拟机将常量池内的标志引用替换为直接引用的历程。

       符号引用(Symbolic
Reference):符号引用以同一组符号来讲述所引用的靶子,符号可以是别形式的字面量,只要使用时能随便歧义地定位到对象即可。符号引用和虚拟机实现之内存布局无关,引用的目标并不一定已经加载到内存中。

       直接引用(Direct
Reference):直接引用得是直接针对目标的指针、相对偏移量或是一个可知间接定位及目标的句柄。直接引用是与虚拟机实现之内存布局相关的,如果生了直白引用,那么引用的对象定已经以内存中留存。

    e 初始化:

     
 类初始化是近似加载过程的末段一步,前面的接近加载过程,除了在加载阶段用户应用程序可以经由定义类加载器参与之外,其余动作了是因为虚拟机主导与操纵。到了初始化阶段,才真正开始实践类中定义之Java程序代码。

     
 初始化阶段是执行类构造器<clinit>()方法的过程。<clinit>()方法是由编译器自动收集类中的富有类似变量的赋值动作以及静态语句块(static{}块)中之语句合并有的。

 

 

2,关于类的 初始化:什么时候才能够触发初始化?

     也便是
什么动静下得开类加载过程的率先单级次:”加载”。虚拟机规范着并无强行约束,这点好付出虚拟机的之切切实实贯彻自由把握,

   
 但是对于初始化阶段虚拟机规范是严厉规定了如下几栽状况,如果类似非初始化会对类进行初始化。

  1. 创造类的实例
  2. 访问类的静态变量(除常量【被final修辞的静态变量】原因:常量一种植奇特的变量,因为编译器把她们当作值(value)而休是所在(field)来对比。如果你的代码中因故到了时常变量(constant
    variable),编译器并无见面生成字节码来起目标吃满入域的价,而是径直将这值插入到配节码中。这是如出一辙种植十分有因此的优化,但是只要您用改final域的值那么每一样片用到那个域的代码都急需更编译。
  3. 访问类的静态方法
  4. 反射如(Class.forName(“my.xyz.Test”))
  5. 当年始化一个类时,发现那父类还未初始化,则优先出发父类的初始化
  6. 虚拟机启动时,定义了main()方法的百般类先初始化

上述情形称称对一个接近进行“主动引用”,除本条种植情况外,均未见面触发类的初始化,称为“被动引用”

接口的加载过程与类似的加载过程稍有两样。接口中未可知利用static{}块。当一个接口在初始化时,并无要求其父接口全部都做到了初始化,只有真正以利用到父接口时(例如引用接口中定义之常量)才会初始化。

 

 

3,关于 类加载器

 

   
 JVM的类加载是由此ClassLoader及其子类来完成的,类的层系关系和加载顺序可以由下图来讲述:

 

图片 5

 

   

1)Bootstrap ClassLoader

当加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类

2)Extension ClassLoader

担负加载java平台受到扩大功能的片段jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下之jar包

3)App ClassLoader

负责记载classpath中指定的jar包及目录中class

4)Custom ClassLoader

属应用程序根据自家需要由定义的ClassLoader,如tomcat、jboss都见面基于j2ee规范活动实现ClassLoader

加载过程中会预先检查类是否被早已加载,检查各个是自底向上,从Custom
ClassLoader到BootStrap ClassLoader逐层检查,

万一有classloader已加载就即已经加载此类,保证此类只拥有ClassLoader加载一坏。而加载的依次是自顶向下,也就算是由于上层来逐层尝试加载此类。

 

 

本文来源:http://www.cnblogs.com/javaee6/p/3714716.html 
 http://m.blog.csdn.net/gjanyanlig/article/details/6818655

 

相关文章