美文网首页
第七章 虚拟机类加载机制

第七章 虚拟机类加载机制

作者: 一颗北上广的心 | 来源:发表于2017-04-25 11:02 被阅读0次

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

类生存过程:类加载-使用-卸载
类加载过程 : 加载-连接-初始化
连接过程: 验证-准备-解析

过程说明

  • 加载
  1. 通过一个类的全限定名来获取定义此类的二进制字节流.
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构.
  3. 在内存中生成一个代表这个类的Class对象,作为方法区这个类的各种数据访问入口.
  • 验证

为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全.
文件格式验证,元数据验证,字节码验证,符号引用验证.

  • 准备

正式为类变量分配内存并设置类变量(static 修饰的) 初始值,这些变量所使用的内存都将在方法区中进行分配.

class Test{
    int x ; // 对象实例化的时候会分配
    static int y =123; //准备后为0, 初始化后为123
    static final int z = 123;//准备后为123
}
  • 解析

    虚拟机将常量池内的符号引用替换为直接引用.

  • 初始化

    初始化阶段是执行类构造器<clinit>()方法的过程.

  • <clinit>()方法由编译器自动收集类中的所有类变量(static变量)的赋值动作和static语句块中的语句合并产生.

  • 虚拟机保证子类的<clinit>()执行之前父类的已经执行完毕.

  • 虚拟机会保证一个类的<clinit>()方法在多线程的环境中被正确的加锁,同步.

5种触发初始化的情况:

  • new对象,read/write static field(except final static field), invoke static method,如果发现这个类没有被加载过;
  • java.lang.reflect反射的未初始化的类
  • 初始化一个类,如果他的父类未初始化过
  • 虚拟机启动时那个带main方法的主类
  • 如果解析结果是REF_getStatic,REF_putSTatic,REF_invokeStatic,所对应的类没有初始化过

类中static初始化:
static字段和static语句块按照先后顺序被<clinit>()收集并执行。父类的优先于子类执行。

public class SubCls extends Parent {

    static String sub_y = "sub static field y";

    static {
        System.out.println("sub static block");
        sub_x = "sub static block x";
        sub_y = "sub static block y";
        // System.out.println(sub_x); can not use the field after the block
    }

    static String sub_x = "sub static field x";

    public static void main(String[] args) {
        System.out.println(sub_x); // static field x
        System.out.println(sub_y); // y - static block
    }
}
class Parent {

    static String p_x = "parent static field x";

    static {
        System.out.println("parent static block");
        p_x = "parent static block x";
    }
}
parent static block
sub static block
sub static field x
sub static block y

双亲委派模型

工作过程:

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。每一个层次的类加载器都是如此。只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。

好处:

Java类随着他的类加载器一起具备了一种带有优先级的层次关系。相反如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户编写了一个称为java.lang.Object的类,并防在ClassPath中,那系统中将出现多个不同的Object类。

类加载器:

  • 启动类加载器(Bootstrap ClassLoader): C++ ; <JAVA_HOME>\lib
  • 扩展类加载器(Extension ClassLoader):JAVA ;<JAVA_HOME>\lib\ext
  • 应用程序类加载器(Application ClassLoader): JAVA ; ClassPath
  • 自定义类加载器(User ClassLoader)

相关文章

网友评论

      本文标题:第七章 虚拟机类加载机制

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