虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。下面来总结梳理类加载的五个阶段。

类加载发生在程序运行期间,会有一些性能开销,但是会提供灵活性,Java动态扩展的特性就是依赖运行时期动态加载和动态连接特点

类加载分为五个阶段:

  1. 加载
  2. 验证
  3. 准备
  4. 解析
  5. 初始化

后四个阶段统称为“连接”阶段

加载

加载阶段,虚拟机完成以下三件事:

  • 通过一个类的全限定名来获取此类的二进制字节流(即class文件);
  • 将字节流的静态存储结构转化为方法区的运行时数据结构;
  • 内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问接口;

注意

  1. 虚拟机规范中未规定方法区中的运行时数据结构,由虚拟机自行定义;
  2. 实例化的java.lang.Class对象未明确规定存储在堆中,HotSpot中的class对象存在方法区中

加载阶段尚未完成时,后续连接解读那可能已经开始

验证

验证阶段主要是为了确保class文件字节流中的信息符合虚拟机要求,不会危害虚拟机自身安全。主要有以下几种格式验证:

  • 文件格式验证:验证是否符合Class文件规范
  • 元数据验证:字节码语义分析,是否符合Java语言要求
  • 字节码验证:验证类的方法体,保证运行不会产生危害
  • 符号引用验证:验证符号引用是否能找到对应的类,是否具有访问权限等

对于反复使用和验证过的代码,可以使用-Xverify:none 可以关闭类验证措施,以缩短类加载时间。因为平时开发中idea和eclipse等工具的验证功能很完善,能保证代码准确。

准备

为static变量分配空间,不包括实例变量,实例变量会在对象实例化时和对象一起分配在堆中,

  • static分配空间在“准备”阶段(在方法区中分配),赋值在“初始化”阶段。例如 public static int value = 123 会在准备阶段设置初始值0,在初始化阶段赋值“123”;
  • static+final修饰基本数据类型和字符串常量时,分配空间和赋值都是在准备阶段,可以借此优化代码
  • static+final修饰引用类型,即用new初始化时,是在构造方法中分配空间和赋值,即在初始化阶段完成

解析

将常量池中的符号引用解析为直接引用。那么问题来了,什么是符号引用和直接引用:

  • 符号引用:描述目标的符号,与虚拟机内存布局无关,以字面量的形式明确定义在class文件中。Java虚拟机内存布局各不相同,但是符号引用必须一致。Java类编译时,不知道引用的类的实际地址,因此使用符号引用。
  • 直接引用:直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。同一个符号引用在不同虚拟机实例上翻译出来的直接引用一般不会相同。

解析动作针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。

初始化:

常说的“类加载时机”与“初始化时机”一一对应。因为要进入初始化阶段,就必须要完成加载、验证、准备、解析等阶段。

初始化发生时机如下:

  • main方法所在类总是会被首先初始化
  • 首次访问这个类的静态变量或静态方法时会导致初始化
  • 子类初始化会联动父类初始化
  • 通过子类访问父类静态变量,只会触发父类初始化
  • Class.forName
  • new会导致初始化

以下情况不会导致类初始化的情况:

  • static final不会触发初始化
  • 访问类对象.class
  • 创建该类的数组
  • 类加载器的loadClass方法
  • Class.forName的参数2为false

初始化阶段实际上是执行类构造器<clinit>()方法的过程。<clinit>()会根据源文件中顺序收集类中所有类变量赋值动作和static块语句

注意:static块能访问代码块之前的变量,之后的变量可以赋值,但不能访问

<clinit>()方法的执行有如下特点:

  • 第一个执行clinit方法的一定是Object类
  • 父类中静态语句块一定优先于子类
  • 如果类中没有static方法和变量,不会产生clinit方法
  • 接口中如果有static变量,也会生成clinit,但是子接口不会执行父接口中的clinit,接口的实现类也不会调用接口中的clinit
  • 多线程时,只会有一个线程会去执行clinit,会加锁,保证线程安全

【JVM】类加载时机与过程的更多相关文章

  1. 从一道面试题来认识java类加载时机与过程

    说明:本文的内容是看了<深入理解Java虚拟机:JVM高级特性与最佳实践>后为加印象和理解,便记录了重要的内容. 1  开门见山 以前曾经看到过一个java的面试题,当时觉得此题很简单,可 ...

  2. java类加载时机与过程

    转自:http://www.tuicool.com/articles/QZnENv 说明:本文的内容是看了<深入理解Java虚拟机:JVM高级特性与最佳实践>后为加印象和理解,便记录了重要 ...

  3. 从一道面试题来认识java类加载时机与过程【转】

    说明:本文的内容是看了<深入理解Java虚拟机:JVM高级特性与最佳实践>后为加印象和理解,便记录了重要的内容. 1  开门见山 以前曾经看到过一个java的面试题,当时觉得此题很简单,可 ...

  4. 【转载】java类加载时机与过程

    1  开门见山 以前曾经看到过一个java的面试题,当时觉得此题很简单,可是自己把代码运行起来,可是结果并不是自己想象的那样.题目如下: class SingleTon { private stati ...

  5. 【深入Java虚拟机】一 JVM类加载过程

    首先Throws(抛出)几个自己学习过程中一直疑惑的问题: 1.什么是类加载?什么时候进行类加载? 2.什么是类初始化?什么时候进行类初始化? 3.什么时候会为变量分配内存? 4.什么时候会为变量赋默 ...

  6. JVM类加载过程学习总结

    JVM类加载过程学习总结 先不说JVM类加载的原理,先看实例: NormalTest类,包含了一个静态代码块,执行的任务就是打印一句话. /** * 在正常类加载条件下,看静态代码块是否会执行 * @ ...

  7. (二十七)JVM类加载器机制与类加载过程

    一.Java虚拟机启动.加载类过程分析 下面我将定义一个非常简单的java程序并运行它,来逐步分析java虚拟机启动的过程. package org.luanlouis.jvm.load; impor ...

  8. JVM类加载过程详细分析

    双亲委派加载模型 为什么需要双亲委派加载模型 主要是为了安全,避免用户恶意加载破坏JVM正常运行的字节码文件,比如说加载一个自己写的java.util.HashMap.class.这样就有可能造成包冲 ...

  9. JVM -- 类加载的过程

    类的加载过程? 一个Java文件从编码完成到最终执行,一般主要包括"编译"和"运行"两个过程.编译,即把我们写好的java文件,通过javac命令编译成字节码, ...

随机推荐

  1. ABBYY FineReader 15 PDF有哪些好用的功能?

    ABBYY FineReader 15(Windows系统)OCR文字识别软件中的PDF编辑器,是一个对用户相当友好的编辑器,不仅可以在其中查看,搜索PDF文档,还可以用以编辑文本,添加备注,添加与删 ...

  2. FL studio系列教程(十一):FL Studio中如何混音

    要想得到"商业"品质的声音,我们就要学会混音.混音就是声音从乐器通道到路由到混音器.混音器中可以设置电平并添加各种效果,比如,添加混响.合唱以及延迟等等,这就是所谓的混音.那么FL ...

  3. MyBatis的一二级缓存

    一级缓存 一级缓存默认是开启的,生命周期和SqlSession相同.一个会话中每次执行一个查询操作时,会先查询二级缓存,如果二级缓存没查到或者二级缓存未开启就会从一级缓存中查询,如果一级缓存也未查到就 ...

  4. 【PUPPETEER】初探之元素获取(二)

    一.涉及的知识点 如何使用css selector 常用元素获取 $ 元素选择 type (api 输入) click (api 点击) 二.学习网址 https://github.com/Googl ...

  5. Ubuntu sudo 出现unable to resolve host 解决方法

    Ubuntu sudo 出现unable to resolve host 解决方法 Ubuntu环境, 假设这台机器名字叫abc(机器的hostname), 每次执行sudo 就出现这个警告讯息: s ...

  6. JS你所不知的小数取整方法

    先介绍几种基本方法. 1.toFixed()方法 toFixed() 方法是属于 Number 对象的方法,可以把 Number 四舍五入到指定的小数位数,括号内为小数位数,范围为0~20,为0时即取 ...

  7. HDU4632 Palindrome subsequence

    标签(空格分隔): 区间qp Palindrome subsequence \[求一个string的 回文子序列 的个数 \] 少废话,上代码. #include<bits/stdc++.h&g ...

  8. 自学linux——18.FTP服务器的搭建

    Centos7下FTP服务器的搭建 一.FTP的作用 文件传输协议(File Transfer Protocol,FTP),是一种在互联网中进行文件传输的协议,基于客户端/服务器模式,默认使用 20. ...

  9. 谈谈 rm -rf * 后的几点体会(年轻人得讲码德)

    事情始末 平时经常开玩笑,删库跑路.删库跑路,今天我真的rm -rf *了.早上来,一个同事说要查日志,但是日志我又备份到云磁盘了,我就想着把那一天的日志wget下来看看,然后分析.本来是想放在/va ...

  10. 从Paxos到Zookeeper 分布式一致性原理与实践读书心得

    一 本书作者介绍 此书名为从Paxos到ZooKeeper分布式一致性原理与实践,作者倪超,阿里巴巴集团高级研发工程师,国家认证系统分析师,毕业于杭州电子科技大学计算机系.2010年加入阿里巴巴中间件 ...