JVM中类加载的过程

引言

众所周知,Java的slogan就是"Write once, run anywhere.",这也就意味着无论我们在什么平台的机器上用Java去做实现,都可以在任何支持Java的系统上直接运行,无需做任何额外操作。
Java是如何做到这些的呢?答案是JRE。

  • 那么什么是JRE?为什么叫JRE?
    • JRE(Java Runtime Environment),是一个Java代码的运行时环境,属于软件层,运行在操作系统软件之上,属于JDK的一部分。
  • 什么是JDK?
    • JDK(Java Development Kit),每一个JDK都包含了一个兼容的JRE和一个JVM,并且JDK包含了许多Java开发人员常用的工具以及类库,比如javacjavajarjmapjstatjstackjinfort.jar等。
  • 什么是JVM?
    • JVM(Java Virtual Machine),JVM可以理解为是一个运行在操作系统之上的虚拟电脑,当我们通过javac*.java编译成JVM可识别*.class字节码文件后,再执行java,此时JVM会将*.class字节码文件解释成当前操作系统平台可识别的机器码去执行。这样的话就实现了"Write once, run anywhere."。
  • 整体流程如下所示

JVM类加载的过程

加载阶段:

  1. 通过类的全限定名来读取class字节码文件的二进制流
  2. 将字节流中的静态数据结构转化为方法区的运行时数据结构
  3. 在内存中生成代表这个类的java.lang.Class对象,作为方法区中这个类中的各种数据结构的访问入口
  • 注意:
    • 这只是类加载的其中一个阶段,不要和类加载混淆
    • 加载阶段和链接阶段中的部分动作是交叉进行的,加载阶段尚未完成,链接阶段可能已经开始

链接阶段(linking)

  1. 验证
    1. 文件格式验证:确保class文件的字节流中包含的信息符合虚拟机规范,并且不会危害虚拟机自身的安全
    2. 元数据验证:语义分析
      1. 是否有父类(除java.lang.Object外,所有的类都必须有父类)
      2. 是否继承了不该继承的类
      3. 如果不是抽象类,是否实现了父类或接口中要求实现的所有方法
      4. 字段、方法是否与父类冲突
    3. 字节码验证:
      1. 确定语义合法、符合逻辑
      2. 类的方法不会做出危害虚拟机的事件
    4. 符号引用验证:发生将符号引用转化为直接引用的时候 -> 解析时
      1. 全限定名是否能找到对应的类
      2. 指定类中是否存在被引用的方法和字段
      3. 符号引用中的类、字段、方法的访问性是否可以被当前类访问(private、protected、public、default)
  2. 准备:
    1. 为类变量(被static修饰的)在方法区中分配内存,实例变量在对象实例化时分配在Java堆中
    2. 设置初始值,此时是赋零值,真正的值在初始化时完成赋值;finnal例外,直接赋值;
    public static int value = 99;
    public static final int value = 99;
    准备阶段结束后
    public static int value = 0;
    public static final int value = 99;
    
  3. 解析:将常量池中的符号引用替换为直接引用
    1. 类或接口解析
    2. 字段解析
    3. 类方法解析
    4. 接口方法解析

初始化

  1. 这是类加载过程的最后一步,除了在加载阶段用户可以通过自定义类加载器参与,其他阶段皆由虚拟机主导和控制
  2. 在该阶段开始真正初始化类中定义的Java程序代码(或者说是字节码),调用<clinit>()
    在遇到以下几种情况时,触发初始化:
    • 当虚拟机启动时,初始化用户指定的主类;
    • 当遇到用以新建目标类实例的 new 指令时,初始化 new 指令的目标类;
    • 当遇到调用静态方法的指令时,初始化该静态方法所在的类;
    • 当遇到访问静态字段的指令时,初始化该静态字段所在的类;
    • 子类的初始化会触发父类的初始化;
    • 如果一个接口定义了 default 方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化;
    • 使用反射 API 对某个类进行反射调用时,初始化这个类;
    • 当初次调用 MethodHandle 实例时,初始化该 MethodHandle 指向的方法所在的类。

至此,一个字节码文件便已经初始化完成。

本文总结

加载一个class类的过程总体分三个步骤,加载、链接、初始化,其中链接阶段分为验证、准备、解析三个阶段,加载阶段通过类的全限定名来读取class字节码文件的二进制流,并将字节码数据转化为方法区的运行时数据结构。链接阶段中的验证阶段对字节码文件进行格式和安全校验,准备阶段为类中的部分变量(被static修饰的变量)分配内存和初始值的赋值,解析阶段将常量池中的符号引用替换为直接引用。初始化阶段会将静态代码的赋值操作和静态代码块中的代码交给<clinit>()方法进行初始化,完成变量的赋值已经资源的分配。

相关问题

虚拟机是如何做到通过类的全限定名去找到对应的Class文件的?

什么是符号引用和直接引用?

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

推荐阅读更多精彩内容