您的位置:首页 > 编程语言 > Java开发

Java类加载机制

2018-03-27 13:13 204 查看
    上文我们说到了JVM的内存模型,本文我们进一步的介绍JVM的类加载机制,先上一张很经典的图:
            


    由该图,我们开始展开探讨。上图将类加载的步骤分为七步,加载,验证,准备,解析,初始化,使用,卸载。

    一、加载
    加载的核心目的是为了将类信息读到内存中,Java中提供一个java.lang.ClassLoader的loadClass()方法,具体步骤一共细分为如下几步:

    1.通过全类名获取字节码文件

    2.将改字节码存储的内容转化为方法区中类的数据结构

    3.在内存中生成一个Class对象,作为访问方法区数据的入口

    二、验证

    验证是连接的第一步,他的主要作用是用于检查二进制文件的合法性,只有当他符合JVM的要求才有效,否则可能会造成当前虚拟机的安全危害。

    三、准备

    是一个给类的静态变量在方法区分配内存并赋初始值阶段(非static修饰过的变量是在堆中分配空间,是在对象被实例化才开始分配),如:
public static int value=123;    在准备阶段,它的值是0,只有到初始化阶段,他才会被赋值123。
    四、解析

    将常量池中的符号引用替换为直接引用的过程。(未理解)

    五、初始化

    为类加载连接的最后一步。当这个阶段,才开始执行Java代码,执行静态代码块,设置静态变量的值为程序员的预定值。

    一下情况下会初始化类:

    new一个对象时(仅仅定义是不会初始化的);
    读取类的静态变量以及静态方法时;

    使用反射调用未被初始化的类时;(这个并无特别解释,只是在验证时发现,获取只有通过Class.forName()获取Class对象时,才会初始化,通过类名.class,并不会初始化,即使调用了Class对象中的方法)

    初始化一个类时,会初始化他的父类;

    JVM启动时,main方法的那个类;

        类初始化时,有父类的子类的初始化顺序:
    1、按照出现顺序,会依次初始化父类静态变量和静态代码块;

    2、再按照出现顺序,依次初始化子类的静态变量和静态代码块;

    3、初始化父类的普通变量以及构造方法;

    4、初始化子类的普通变量和构造方法;

    补充一个很经典的类加载例子:
public class SuperClass {
static{
System.out.println("SuperClass init!");
}
public static int value=123;

}
public class SubClass extends SuperClass {
static{
System.out.println("SubClass init!");
}

}
public class NotInitialization {

public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(SubClass.value);

}

}    以上代码的执行结果为:
    SuperClass init!

    123
    由此得出结论,通过子类调用父类的静态变量,只会初始化父类,并不会初始化子类。对于静态字段来说,只有直接定义静态字段的那个类会被初始化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JVM Java