Class 装载系统

来源:互联网 发布:硬盘坏了恢复数据 编辑:程序博客网 时间:2024/06/05 01:12
Class 装载系统
一.Class 文件的装载流程
    1.加载 class 文件的流程:加载 -->连接(验证,准备,解析)--> 初始化
      只有被 JAVA 虚拟机装载的 Class 类型才能在程序中使用
    2.类装载的条件 :Class 只有在使用的时候才会被java虚拟机加载,使用Class 的情况:
        a.创建一个类的实例时,比如使用了 new 关键字,或者通过反射,克隆,反系列化
        b.调用了类的静态方法的时候,即使用了字节码的 invokestatic 指令
        c.使用了类或接口的静态字段(final常量除外),比如使用了getstatic 或者 putstatic指令
        d.使用了java.lang.reflect 包中的方法反射类的方法时
        e.初始化子类时,要求先初始化父类
        f.作为启动虚拟机,含有 main() 方法的那个类
    注意:只有主动使用的类才会被java虚拟机初始化,只有初始化的类才能够使用。不被使用的类可能会被加载
          在不会被初始化 , 可以使用  -XX:+TraceClassLoading  参数,查看类是否被加载 。
          被 final 修饰的常量,直接放在常量池中,不会引起类的加载
    3.加载类:类装载的第一阶段,在加载类时必须呀完成如下工作
        a.通过类的全类名,获取类的二进制数据流
        b.解析二进制数据流为方法去内的数据结构
        c.创建java.lang.Class 类的对象,表示该类型
      java 虚拟机可通过文件系统读入一个Class 后缀的文件,或者可能是 jar 或者 zip 等归档数据包
    4.验证类 :当类加载到文件系统中,就开始连接操作了,验证就是连接操作的第一步。目的是保证加载的
               字节码是合法、合理并符合规范的。
        a.必须判断类的二进制数据是否是符合格式要求和规范
        b.对字节码进行语意的检查
        c.对字节码进行验证,字节码的验证是验证过程中最为复杂的一个过程
        d.还将进行符号引用的验证
    5.准备:当一个类通过验证时。虚拟机就会进入准备阶段,在这个阶段,虚拟机就会诶这个类分配内存空间
        并设置初始值
    注意:java 并不支持 boolean 类型,对于 boolean 类型,内部是现实 int ,由于 int 默认值是0,
          故对应的,boolean 的默认值就是 false
    6.解析类:将类、接口、字段和方法的符号引用转为直接引用
      符号引用:一些字面量的引用,和虚拟机的内部数据结构和内存布局无关
      直接引用:符号引用转变为目标方法在类中方法表中的位置,从而使得方法被成功调用
    7.初始化:是类装载的最后一个阶段,如果前面的步骤都没有问题,那表示类就可以顺利的装载到系统中
      注意:子类的 static 块优先级高于父类
            类的加载也有可能会引起线程的死锁问题

二.ClassLoader :是 java 的核心组件,所有的 Class 都是有 ClassLoader 加载,ClassLoader 通过各种方式将
         Class 信息的二进制流读入系统,然后交给 java 虚拟机进行连接、初始化等操作。
    1.类的加载
      双亲加载机制
    2.ClassLoad 的分类
      a.BootStrap ClassLoader 启动类加载器 :加载核心类
      b.Extension ClassLoader 扩展类加载器 :加载 %JAVA_HOME%/lib/*.jar 中的java类
      c.App ClassLoader 系统类加载器    : 加载用户类
     注意:
        检查类是否存在,自底向上检查类是否加载
        加载类,自顶向下加载
      java 类的核心类,基本都是由 BootStrap ClassLoader 加载的
    3.ClassLoader 的双亲委托模式
        系统判断当前类是否已经被加载的时候,如果该类没有被加载,系统会尝试加载该类,在
        加载该类的时候,会请双亲处理,如果双亲请求失败,则会自己加载。
      注意:
          判断类是否加载的时候,应用加载器会顺着双亲路径往上判断,直到启动类加载器
          但是启动类不会往上询问,这个委托路线是单向的
    4.双亲委托模式的弊端
      检查类是否已经被加载的委托过程是单向的,就会导致顶层的 ClassLoader 无法访问底层的
      ClassLoader 所加载的类
    5.双亲委托模式的补充
      在 java 平台中 ,把核心类(rt.jar)中提供外部服务,可有应用层自行实现接口,通常
      可以称为 Service Provider Interface 即SPI
    6.突破双亲模式
      双亲模式的类加载模式是虚拟机的默认行为,但并非不许这样做,通过重载 ClassLoader
      可以修改该行为。很多软件就修改了这种行为,比如 TomCat
      自定义自己的 ClassLoader 加载器 ,当顶层 ClassLoader 判断返回对象是 null 则
      颠倒默认的加载顺序
    7.热替换 (需要重载 ClassLoader )
      在程序运行过程中,不停止服务,只通过替换程序文件来修改程序的行为
      在这里需要注意的是,由不同的ClassLoader 加载同名类 属于不同的类型,不能相互的
      转化和兼容