虚拟机类加载机制

很多人觉得会写Java代码就行,Java底层怎么运行的不需要知道,但其实并不是这样,随着经验的积累,你需要了解越来越多的底层原理。我们先来看看下面的代码,看看class是怎样加载的。

public class BaseClass {
    static {
        System.out.println("BaseClass Init");
    }

    public static final String value = "BaseClass";
}

public class SubClass extends BaseClass {
    static {
        System.out.println("SubClass Init");
    }
}

public static void main(String[] args) {
    System.out.println(SubClass.value);
}

定义了一个父类BaseClass和子类SubClass,执行main方法会输出父类的“BaseClass Init”,而不是子类的,对于静态字段,,子类调用父类的静态字段吗,只会触发父类的初始化,而不会出发子类的初始化,为什么呢?下面我们来看下类的生命周期:
类从被加载到JVM内存中开始,到卸载出内存为止,它经历过了7个过程,包含加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading),其中验证、准备和解析称为连接。如图:


图片

图中可以看到解析和初始化有个双向箭头标注,这是因为支持Java的运行时绑定(动态绑定/晚期绑定)可以初始化开始后在执行解析,其它加载、验证、准备、初始化和卸载的顺序是确定的。对于初始化阶段,JVM规范严格规定了只有5中情况立即对类进行“初始化”(而加载、验证、准备自然需要在此之前开始):

  • 遇到new、getstatic、putstatic或invokestatic这4个字节码指令时

  • 使用java.lang.reflect包的方法对类进行反射时

  • 初始化子类,发现父类没有初始化需要触发父类的初始化

  • 虚拟机启动时,指定一个要执行的类(包含main方法的那个类)

  • 使用JDK1.7动态语言支持时,java.lang.invoke.MethodHandle实例最后的解析结果是REF_getstatic、REF_putstatic和REF_invokestatic的方法句柄时

  • 加载:加载时类加载过程的第一个阶段,在加载阶段,虚拟机需要完成以下三件事情:

    • 通过一个类的全限定名来获取其定义的二进制字节流。
    • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
    • 在Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口。

加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,而且在Java堆中也创建一个java.lang.Class类的对象,作为程序访问方法区中这些类型数据的外部接口。

  • 验证:是连接阶段的第一步,为了确保class文件的字节流中包含的信息符合当前虚拟机要求,并且不会伤害虚拟机自身的安全。需要完成下面4个检验动作:
    • 文件格式验证:验证字节流是否符合文件格式的规范,并且能被当前版本的虚拟机处理,例如:以魔数0xCAFEBABE开头、主次版本号是否被接受、是否有不支持常量类型等等
    • 元数据验证:对字节码描述的信息进行语义分析,以保证其描述的信息符合java语言规范,例如:是否有父类、父类是否继承了不允许被继承的类、类的字段和方法是否和父类冲突等等
    • 字节码验证:通过数据流和控制流分析,确定语义是合法的、符合逻辑的。例如:保证跳转指令不会跳转到方法体以外的字节码指令伤、保证方法体中的类型转换是有效的等等
    • 符号引用验证:可以看做是对类自身以外(常量池中的各种符号引用)的信息进行匹配性校验。
  • 准备:正式为类的变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。这里需要注意下两点:
    • 进行内存分配的时候仅包括类变量(被static修饰的变量),而不包括实例变量,它将会在对象实例化时随着对象一起分配Java堆中。
    • 初始值通常情况下是数据类型的零值,例如:public static int value = 2; 变量value在准备阶段过后初始值为0而不是2。

| 数据类型 | 默认值 | 数据类型 | 默认值 |
|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
| int | 0 | long | 0L |
| short | (short)0 | char | ‘\u0000’ |
| byte | (byte)0 | boolean | false |
| float | 0.0f | double | 0.0d |
| reference | null | | |

  • 解析:将常量池内的符号引用替换为直接引用的过程。主要针对类、接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。
    • 符号引用:以一组符号来描述所引用的目标
    • 直接引用:直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄
  • 初始化:类加载过程的最后一步,是执行类构造器<clinit>()方法的过程。

总结

类加载过程中主要是将Class文件(准确地讲,应该是类的二进制字节流)加载到虚拟机内存中,真正执行字节码的操作,在加载完成后才真正开始。整个类加载过程中,除了在加载阶段可以自定义类加载器参与之外,其余所有的动作完全由虚拟机主导和控制。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容