您的位置:首页 > 其它

JVM类加载机制详细解析

2017-10-25 15:03 387 查看
类的生命周期:
    加载->链接(验证->准备->解析)->初始化->使用->卸载     
              (连接阶段Linking)

1、加载:
加载过程主要完成的3件事情:
            >>通过类的全限定名来获取定义此类的二进制字节流。
            >>将字节流所代表的静态存储结构转化为方法区的运行数据结构。
            >>在Java堆中生成对应这个类的java.lang.Class对象,作为方法区中这个类的访问入口。
        注:加载完成后,虚拟机外部的二进制字节流就会存储在方法区中。

2、链接-->验证
    --目的:确保Class文件的字节流中包含和信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。主要内容如下:
        文件格式的验证 (是否以0xCAFFBABE开头,版本号是否正确);
        元数据验证 (是否有父类,继承了final,非抽象类实现了所有的抽象方法)
        字节码验证 (运行检查,通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。)
    
3、链接-->准备
    正式为类变量分配内存(static修饰的变量)并设置类变量初始值(0/false/0.0f/null等而不是变量的实际值)。
    特殊情况:public
static final int value = 123; 准备阶段会被赋值为123.而不是0.

4、链接-->解析
      将常量池内的符号引用替换为直接引用的过程。
    解析调用一定是个静态的过程,在编译期就完全确定,在类加载的解析阶段就将涉及的符号引用全部转变为可以确定的直接引用,不会延迟到运行期再去完成。

5、初始化
    执行类构造器<clinit>
        -static变量,复制语句
        -static{}语句
    子类的<clinit>调用前要保证父类的<clinit>被调用

    
    初始化时机:
            >>遇到new、getstatic、putstatic 或 invokestatic 字节码指令,如果类没有进行初始化,则进行。
            >> 使用java.lang.reflect包的方法对类进行反射调用时,如果类没有进行初始化,则进行初始化。
            >>初始化一个类,如果其父类没有初始化,则先触发父类的初始化。
            >>JVM启动,先初始化main方法所在的类。
        注:类不会被初始化的3种场景p211.

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



比较两个类相等,只有两个类由同一个类加载器加载的前提下才有意义,否则即使这两个类源于同一个Class文件,被同一个虚拟机加载,只要加载他们的类加载器不同,那么这两个类也必定不相等。双亲委派委派模型是的Object及其子类最终都有启动类加载器加载,因此Object类在各种类加载器环境中的都是同一个类。 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: