我们都知道以 .java 结尾的 Java 源文件,经过编译之后会变成 .class 结尾的字节码文件。JVM 通过类加载器来加载字节码文件,然后再执行程序。

什么时候加载一个类

那么,什么时候类加载器会加载一个类呢?用到这个类的时候,JVM的类加载器就会加载这个类。用到这两个字说起来很抽象,我用代码和图例来说明。

有下面这样一段代码,一个类EmergencyPlan,里面有一个main()函数,main()函数做的事情是创建了一个 Account 对象。

public class EmergencyPlan {
public static void main(String[] args) {
Account account = new Account();
}
}

我们应该知道运行 JVM 就相当于启动了一个 Java 的进程,它会从程序的主函数,即main()函数开始执行。所以类加载的步骤是这样的:

  1. 先加载主函数所在的类EmergencyPlan
  2. 由于EmergencyPlan使用了Account,所以继续加载Account

准备和初始化的区别

类加载机制总共有这样7个步骤:加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载。接下来先把每个阶段在做什么讲一下,再着重对比一下准备阶段和初始化阶段。

  • 验证阶段:验证字节码文件是否符合JVM的规范。这挺好理解,万一字节码文件被修改过,JVM压根无法执行咋办。所以加载之后先验证一下。
  • 准备阶段:为类分配内存空间,为变量赋初值。
  • 解析阶段:符号引用替换为直接引用。
  • 初始化阶段:执行初始化代码,new对象;执行static代码块;父类没有初始化要先初始化父类。

用代码和画图来说明一下准备阶段和初始化阶段。

public class EmergencyPlan {
public static int id
= Configuration.getInt("plan_id");
}

这段代码说的是EmergencyPlan这个类有一个变量id,通过getInt()为其赋值:

  • 准备阶段会为id开辟一个内存空间,但不会执行赋值操作,仅仅是赋予一个初值0。
  • 初始化阶段才会执行getInt()为变量id初始化值。

类加载的过程就变成了下图所示的样子:

类加载器和双亲委派模型

JVM进行类加载是通过类加载器完成,类加载器是一种亲子层级结构的模型。Java里面的类加载器有这样几种:

  • 启动类加载器。加载 JDK 中 lib 目录中 Java 的核心类库,即$JAVA_HOME/lib目录。
  • 扩展类加载器。加载 lib/ext 目录下的类。
  • 应用程序类加载器。加载我们写的应用程序。
  • 自定义类加载器。根据自己的需求定制类加载器。

那什么是双亲委派模型呢?类加载器是一种亲自层级结构,就像下图所示:

比如要加载上面的EmergencyPlan类,应用程序类加载器会先问它的父亲扩展类加载器,你能帮我加载么?扩展类加载器会再问它的父亲启动类加载器,你能帮我加载么?

显然EmergencyPlan是一个应用程序类。启动类加载器会告诉扩展类加载器,你自己去加载;扩展类加载器就会告诉应该程序类加载器,你自己去加载。最后,应用程序类加载器就自己加载了EmergencyPlan

流程图总结

最后来在类加载的流程图上,把双亲委派模型也添加上去。

图解JVM类加载机制和双亲委派模型的更多相关文章

  1. Java类加载机制以及双亲委派模型

    一.Java类加载机制 1.概述 Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允 ...

  2. java虚拟机(二)--类加载机制和双亲委派模型

    一.类的生命周期 加载(Loading).验证(Verification).准备(Preparation).解析(Resolution).初始化(Initialization).使用(Using).卸 ...

  3. JVM类加载器以及双亲委派模型

    从java开发人员的角度来看,类加载器可以分为3种: 1.启动类加载器(Bootstrap ClassLoader),负责将存放在<JAVA_HOME>\lib目录中,或者被-Xbootc ...

  4. JVM类加载过程与双亲委派模型

    类加载过程 类加载过程为JVM将类描述数据从.class文件中加载到内存,并对数据进行解析和初始化,最终形成被JVM直接使用的Java类型.包含: 加载:获取该类的二进制字节流,将字节流代表的静态存储 ...

  5. java虚拟机类加载机制和双亲委派模型

    java虚拟机类加载机制:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型. 类的生命周期是从类被加载到虚拟机内存中,到卸 ...

  6. JVM——类加载器的双亲委派模型

    类加载器双亲委派模型,如下图所示: 双亲委派模型的工作过程 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此 ...

  7. jvm类加载器和双亲委派模型

    类加载器按照层次,从顶层到底层,分为以下三种:  (1)启动类加载器(Bootstrap ClassLoader)   这个类加载器负责将存放在JAVA_HOME/lib下的,或者被-Xbootcla ...

  8. 类文件的结构、JVM 的类加载过程、类加载机制、类加载器、双亲委派模型

    一.类文件的结构 我们都知道,各种不同平台的虚拟机,都支持 "字节码 Byte Code" 这种程序存储格式,这构成了 Java 平台无关性的基石.甚至现在平台无关性也开始演变出 ...

  9. 【深入理解JVM】类加载器与双亲委派模型

    原文链接:http://blog.csdn.net/u011080472/article/details/51332866,http://www.cnblogs.com/lanxuezaipiao/p ...

随机推荐

  1. PhaserJS 3 屏幕适配时的小坑 -- JavaScript Html5 游戏开发

    巨坑:在config内不要把 width 设为 window.innnerWidth在config内不要把 width 设为 window.innnerWidth在config内不要把 width 设 ...

  2. Codeforces Round #620 (Div. 2)

    Codeforces Round #620 (Div. 2) A. Two Rabbits 题意 两只兔子相向而跳,一只一次跳距离a,另一只一次跳距离b,每次同时跳,问是否可能到同一位置 题解 每次跳 ...

  3. springmvc与swagger2

    首先呢我们导入相关的jar包文件 为了方便copy我copy一份 <!-- 导入java ee jar 包 -->        <dependency>           ...

  4. hadoop HDFS完全分布式搭建

    1.准备阶段 准备好两台虚拟机(安装好hadoop,见:https://www.cnblogs.com/cjq10029/p/12336446.html),计划: IP 主机名 192.168.3.7 ...

  5. 3DGIS与BIM集成集成技术及铁路桥梁可视化系统

    3DGIS与BIM的集成技术 3DGIS与BIM的集成技术包括2部分:一是将Revit软件生成的BIM针对3DGIS的快速无损格式转换,这种转换包括几何信息(如形状.位置等信息)和属性信息(如建筑信息 ...

  6. R调用C++示例

    sourceCpp {Rcpp}:Source C++ Code from a File or String sourceCpp(file = "", code = NULL, e ...

  7. HashMap底层源码剖析

    HashMap底层源码剖析 一.HashMap底层用到的数据结构 数组+单向链表+红黑树 数组:数组每一项都是一个链表,其实就是数组和链表的结合体 单向链表:当法神hash碰撞时,首先会找到数组对应位 ...

  8. go入门二

    一.流程控制 1.选择结构 if-else: package main import ( "io/ioutil" "fmt" ) func main(){ co ...

  9. (转)ARM GNU常用汇编语言介绍

    ARM GNU常用汇编语言介绍 原文地址:http://zqwt.012.blog.163.com/blog/static/120446842010445441611/ ARM汇编语言源程序语句,一般 ...

  10. [BUG]微信浏览器 iOS input 失焦页面不回弹

    描述 ios13. ios中,input唤醒软键盘后,body整体会向上滚动,如果input框输入完成确定后,如果页面在最底部则不回弹,导致fixed布局实际效果上移,fixed布局内按钮点不到. 如 ...