• 类加载过程

    • 加载
    • 验证
    • 准备
    • 解析
    • 初始化

类加载过程

Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚拟机是如何加载这些 Class 文件呢?

系统加载 Class 类型的文件主要三步:加载->连接->初始化。连接过程又可分为三步:验证->准备->解析。

加载

类加载过程的第一步,主要完成下面3件事情:

  1. 通过全类名获取定义此类的二进制字节流
  2. 将字节流所代表的静态存储结构转换为方法区的运行时数据结构
  3. 在内存中生成一个代表该类的 Class 对象,作为方法区这些数据的访问入口

虚拟机规范多上面这3点并不具体,因此是非常灵活的。比如:"通过全类名获取定义此类的二进制字节流" 并没有指明具体从哪里获取、怎样获取。比如:比较常见的就是从 ZIP 包中读取(日后出现的JAR、EAR、WAR格式的基础)、其他文件生成(典型应用就是JSP)等等。

一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以去完成还可以自定义类加载器去控制字节流的获取方式(重写一个类加载器的 loadClass() 方法)。数组类型不通过类加载器创建,它由 Java 虚拟机直接创建。

类加载器、双亲委派模型也是非常重要的知识点,这部分内容会在后面的文章中单独介绍到。

加载阶段和连接阶段的部分内容是交叉进行的,加载阶段尚未结束,连接阶段可能就已经开始了。

验证

准备

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中分配。对于该阶段有以下几点需要注意:

  1. 这时候进行内存分配的仅包括类变量(static),而不包括实例变量,实例变量会在对象实例化时随着对象一块分配在 Java 堆中。
  2. 这里所设置的初始值"通常情况"下是数据类型默认的零值(如0、0L、null、false等),比如我们定义了public static int value=111 ,那么 value 变量在准备阶段的初始值就是 0 而不是111(初始化阶段才会复制)。特殊情况:比如给 value 变量加上了 fianl 关键字public static final int value=111 ,那么准备阶段 value 的值就被复制为 111。

基本数据类型的零值:

解析

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用限定符7类符号引用进行。

符号引用就是一组符号来描述目标,可以是任何字面量。直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。在程序实际运行时,只有符号引用是不够的,举个例子:在程序执行方法时,系统需要明确知道这个方法所在的位置。Java 虚拟机为每个类都准备了一张方法表来存放类中所有的方法。当需要调用一个类的方法的时候,只要知道这个方法在方发表中的偏移量就可以直接调用该方法了。通过解析操作符号引用就可以直接转变为目标方法在类中方法表的位置,从而使得方法可以被调用。

综上,解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,也就是得到类或者字段、方法在内存中的指针或者偏移量。

初始化

初始化是类加载的最后一步,也是真正执行类中定义的 Java 程序代码(字节码),初始化阶段是执行类构造器 <clinit> ()方法的过程。

对于<clinit>() 方法的调用,虚拟机会自己确保其在多线程环境中的安全性。因为 <clinit>() 方法是带锁线程安全,所以在多线程环境下进行类初始化的话可能会引起死锁,并且这种死锁很难被发现。

对于初始化阶段,虚拟机严格规范了有且只有5中情况下,必须对类进行初始化:

  1. 当遇到 new 、 getstatic、putstatic或invokestatic 这4条直接码指令时,比如 new 一个类,读取一个静态字段(未被 final 修饰)、或调用一个类的静态方法时。
  2. 使用 java.lang.reflect 包的方法对类进行反射调用时 ,如果类没初始化,需要触发其初始化。
  3. 初始化一个类,如果其父类还未初始化,则先触发该父类的初始化。
  4. 当虚拟机启动时,用户需要定义一个要执行的主类 (包含 main 方法的那个类),虚拟机会先初始化这个类。
  5. 当使用 JDK1.7 的动态动态语言时,如果一个 MethodHandle 实例的最后解析结构为 REF_getStatic、REF_putStatic、REF_invokeStatic、的方法句柄,并且这个句柄没有初始化,则需要先触发器初始化。

参考

  • 《深入理解Java虚拟机》
  • 《实战Java虚拟机》
  • https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html

转载于:https://www.cnblogs.com/myseries/p/10980384.html

三、JVM — 类加载过程相关推荐

  1. jvm类加载过程_JVM知识点——深入理解JVM的类加载

    前言: 前面又说到Java程序实际上是将.class文件放入JVM中运行.虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换,解析和初始化,最终形成可以被虚拟机直接使用的Java类 ...

  2. jvm类加载过程_JVM类生命周期概述:加载时机与加载过程

    作者:菜鸟小于 https://www.cnblogs.com/Young111/p/11359700.html 一个.java文件在编译后会形成相应的一个或多个Class文件,这些Class文件中描 ...

  3. JVM—类加载过程学习

    1 类加载过程图解   系统加载Class类型的文件主要是:加载->连接->初始化,其中连接分为:验证->准备->解析:其实,整个生命周期是7步,类从被加载到虚拟机内存中开始, ...

  4. jvm类加载过程_详解JVM类加载

    1. Java对象的创建过程 类加载检查 ===> 分配内存 ===> 初始化零值 ===> 设置对象头 ===> 执行init方法 1.1 类加载检查 虚拟机遇到一条new指 ...

  5. JVM系列(一):JVM类加载过程详解

    Java 通过引入字节码和 JVM 机制,提供了强大的跨平台能力,理解 Java 的类加载机制是深入 Java 开发的必要条件. 一.Java代码执行流程 Java程序运行时,必须经过编译和运行两个步 ...

  6. JVM类加载机制详解(一)JVM类加载过程

    2019独角兽企业重金招聘Python工程师标准>>> 首先Throws(抛出)几个自己学习过程中一直疑惑的问题: 1.什么是类加载?什么时候进行类加载? 2.什么是类初始化?什么时 ...

  7. JVM类加载过程,JDK和JER区别

    java类被加载过程 类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成: ①加载(以二进制形式来生成java.lang.Class对象) ②链接(又分为验证.准备和解析) 校验:检查导入类或 ...

  8. JVM类加载过程和编译器优化

    文章目录 1. 加载 2. 链接 2.1 验证 2.2 准备 2.3 解析 3 初始化 3.1 类初始化练习 3.2 懒汉式单例练习 4. 类加载器 4.1 启动类加载器 4.2 扩展类加载器 4.3 ...

  9. 深入理解Java虚拟机——JVM类加载机制(类加载过程和类加载器)

    一.什么是类加载机制? 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 二.类加载的时机 类 ...

最新文章

  1. 获取数组第N个元素的方法
  2. python isinstance type区别
  3. 计算机网络向用户提供的最重要的功能
  4. python随机生成中文字符串_利用python3随机生成中文字符的实现方法
  5. mysql存储过程模糊查询_Mysql之存储过程“模糊查询drop表”
  6. ASP.NET 2.0中发送电子邮件
  7. Python21天打卡Day14-随机字符串
  8. mysql explain索引_mysql 索引+explain
  9. 串口液晶屏和并口液晶屏的区别
  10. 层级菜单构造--groupingby
  11. 高中信息技术简答题汇总
  12. LayUI的后台管理模板
  13. pyinstaller 打包exe启动慢的问题
  14. SiT2020:抗冲击抗振动宽温振荡器,1-110MHz之间频率,SOT23-5封装
  15. Linux小知识:查看当前最耗费CPU的线程(Arthas工具)
  16. DateAdd 函数
  17. blos禁止计算机休眠,电脑不能休眠待机
  18. 成就亿万富翁的10条规则
  19. 美国在线地图软件测评:谷歌居首必应次之
  20. 学认五线谱-基本乐理

热门文章

  1. Linux shell脚本sed使用
  2. ❤️一分钟学会python条件语句❤️
  3. 动画会震一下css,csshake.css强大的CSS3元素抖动动画库
  4. opencv双线程图片处理_打开正经图片,你可能会看到一张黄图,这种造假方法能同时骗过 AI 和人眼...
  5. centos7 docker端口_使用Docker部署Python应用
  6. Java之StringUtils的常用方法(非常不错)
  7. python 获取网页元素_记一次python提取网页标签元素的坑
  8. c++ list排序_STL之list
  9. sccket服务器信息获取,websocket断线后重新new了地址,ws.onmessage没有数据
  10. 如何在Eclipse中如何自动添加注释和自定义注释风格