虚拟机把描述类的数据从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. web自动化测试--iframe切换

    什么是iframe切换,我们在测试web网页过程中,可能会遇到一个网页中嵌套另一个网页的情况,如下图,就是一个ifame嵌套的例子 我们如何切换呢,别急,webdriver里有方法,可以切换到ifra ...

  2. JAVA8新特性Optional,非空判断

    Optional java 的 NPE(Null Pointer Exception)所谓的空指针异常搞的头昏脑涨, 有大佬说过 "防止 NPE,是程序员的基本修养." 但是修养归 ...

  3. VMware与Device/Credential Guard不兼容问题

    启动虚拟机vmware突然报不兼容错误 解决方法: 1首先打开控制面板>程序>启动或关闭Windows功能, 取消Hyper-v的勾选 2.在往下划,关闭Windows沙盒的勾选沙盒和虚拟 ...

  4. python:列表的去重:两种方法的问题是:结果是没有保持原来的顺序。

    列表的去重 1.使用set的特型,python的set和其他语言类似, 是一个无序不重复元素集 orgList = [1,0,3,7,7,5] #list()方法是把字符串str或元组转成数组 for ...

  5. 03Python网络编程系列之服务端

    # 这里边是一个定义了服务端的一系列函数,是Python网络编程这本书第七章的第一个例子.# 这是供后边函数进行调用了,然后我们来进行研究网络的单线程编程,多线程编程.异步网络编程等.# 导入网络编程 ...

  6. springboot多模块项目搭建遇到的问题记录

    废话不多说,直接上问题报错与解决方法. 问题报错一:(报错信息看下方代码) 问题原因:'com.company.logistics.service.company.CompanyService' 未找 ...

  7. PyQt(Python+Qt)学习随笔:QTableWidget表格部件中行高和列宽的计算方式

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QTableWidget表格部件中行高和列宽的计算在Qt提供的资料中内容介绍比较泛,细节说得不清楚, ...

  8. 第十一章 Python 支撑正则表达式处理的re模块

    re模块是Python中支持正则表达式处理的模块,老猿学了之后,发现这部分内容太多,要表述清楚需要开单章才能写清楚,但老猿觉得re模块的使用对多数人来说要通过教程学习去熟练掌握很难,需要经常接触练习加 ...

  9. PyQt(Python+Qt)学习随笔:Qt Designer中toolBar的allowedAreas属性

    1.概述 allowedAreas属性指定工具栏允许移动的范围,其类型为枚举类Qt.ToolBarAreas,有如下取值: 以上取值可以同or操作组合使用. 2.访问方法 缺省值为Qt.AllTool ...

  10. PyQt(Python+Qt)学习随笔:窗口对象尺寸调整相关的函数resize、showMaximized、showNormal、showMinimized

    resize(width,height) resize可以直接调整窗口的尺寸,调整效果类似于鼠标直接拉伸或缩小窗口,但窗口大小的最大值.最小值受窗口的sizePolicy.sizeHint.minim ...