JVM类的加载与初始化

作者: 沐兮_d64c | 来源:发表于2018-04-02 15:04 被阅读631次

    1,引用一张比较全面的图,描述加载class文件的整个过程。

    1)如图

    1.png
    2)3种类加载器
    image.png
    3)类加载的实际过程
    JDK执行指令寻找jre目录,找到jvm.dll(jvm虚拟机库的位置),初始化JVM。
    JVM产生一个Bootstrap Loader
    BootstrapLoader自动加载ExtClassLoader,将其parent设置为BootstrapLoader
    BootstrapLoader自动加载AppClassLoader,将其parent设置为ExtClassLoader
    最后由AppClassLoader采用双亲委派策略,加载类,目的是保证java.lang.String,java.lang.Object等核心类都是一个,可以自定义类,但是不会被加载
    4)JVM加载class文件会做的事情
    通过类的全限定名获取class文件的二进制字节流。
    将字节流中的静态存储结构,转化成方法区的运行时数据结构。
    在堆中生成一个java.lang.Class对象,作为方法区这些数据的访问入口。
    在准备阶段(为静态域分配存储空间)public static int value = 1;只会为类变量分配内存和初始值,不会执行赋值的初始化动作
    private int i = 2; 实例变量是实例化对象,在堆中分配的,加载类过程不涉及
    5)类的加载,ClassLoader. defineClass:用于将二进制的字节码转成Class对象。如果生成的类名和二进制中的不符,报NoClassDefFoundError异常。二进制的字节码不符合JVM的规范,ClassFormatError

    2,初始化阶段

    1)初始化类的五种条件(对类的主动引用)
    JVM初始化主类,含有main方法的类
    new getstatic putstatic invokestatic 这几条指令时
    初始化子类时,父类未被初始化,则会先初始化父类
    使用Class.forName(String className)加载类时
    使用java.lang.reflect.*的方法对类进行反射调用时
    2)被动引用类时,不会初始化类
    子类调用父类的静态变量,子类不会被初始化,父类会被初始化,但是不会调用构造函数
    创建类的引用数组,该类不会被初始化,eg Main[] list = new Main[10];
    调用类的final静态常量,不会初始化该类
    ClassLoader的loadClass方法只会加载类,不会初始化类
    3)初始化就是执行类的 <clinit>(){……}方法。
    把静态变量的赋值和静态代码块等操作顺序串连成一个方法。

    3,调用顺序的例子

    父类静态块-->子类静态块-->父类构造块-->父类构造函数-->子类构造块-->子类构造函数

    1)Super类 image.png
    2)Sub类 image.png
    3)主类 image.png
    4)执行顺序 image.png

    相关文章

      网友评论

      • 3d82f357f8f9:感谢楼主分享,就是图一太模糊了,有些看不清。略有遗憾

      本文标题:JVM类的加载与初始化

      本文链接:https://www.haomeiwen.com/subject/bypthftx.html