原文地址:https://www.cnblogs.com/study-everyday/p/7009294.html

一、概述

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

二、类加载的生命周期

类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。

其中:验证、准备、解析3个部分统称为连接(Linking)。

加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始,而解析阶段不一定:

在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定(也称为动态绑定或晚期绑定),这里的 "按部就班开始"并不是链式进行,这些阶段通常是相互交叉地混合进行的,通常会在一个阶段执行的过程中调用、激活另外一个阶段。

三、类加载的过程

1. 加载

"加载" 是类加载过程的一个阶段。在加载阶段,虚拟机需要完成以下3件事情:

1)通过一个类的全限定名来获取定义此类的二进制字节流。

2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据访问入口。

加载阶段完成之后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,方法区中的数据存储格式由虚拟机实现自定义,虚拟机规范为规定此区域的具体数据结构。然后在内存中实例化一个java.lang.Class类的对象(并没有明确规定是在Java堆中,对于HotSpot虚拟机而言,Class对象比较特殊,它虽然是对象,但是存放在方法区里面),这个对象将作为程序访问方法区中的这些类型数据的外部接口。

加载阶段与连接阶段的部分内容是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,当这些夹在加载阶段之中进行的动作,仍然属于连接阶段的内容,这两个阶段的开始时间仍然保持着固定的先后顺序。

2.验证

验证是连接阶段的第一步,这阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

4个检验动作:

1)文件格式验证

  • 是否以魔数oxCAFEBABE开头
  • 主、次版本号是否在当前虚拟机处理范围内。
  • 常量池的常量中是否有不被支持的常量类型(检查常量tag标志)。
  • 指向常量的各种索引值中是否有指向不存在的常量或不符合类型的常量。
  • CONSTANT_Utf8_info型的常量中是否有不符合UTF8编码的数据。
  • Class文件中各个部分及文件本身是否有被删除的活附加的其他信息。
  • ……

2)元数据验证

  • 这个类是否有父类(除了java.lang.Object之外,所有的类都应当有父类)。
  • 这个类的父类是否继承了不允许被继承的类(被final修饰的类)。
  • 如果这个类不是抽象类,是否实现了其父类或接口之中要求实现的所有方法。
  • 类中的字段、方法是否与父类产生矛盾(例如覆盖了父类的final字段,后者出现不符合规则的方法重载,例如方法参数都一致,当返回值类型去不同等)。
  • ……

3)字节码验证

  • 保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作,例如不会出现类似这样的情况:在操作栈放置了一个int类型的数据,使用时却按long类型来加载入本地变量中。
  • 保证跳转指令不会跳转带方法体以外的字节码指令上。
  • 保证方法体中的类型转换是有效的,例如可以把一个子类对象赋值给父类数据类型,但是把父类对象赋值给子类数据类型,甚至把对象赋值给与它毫无继承关系、完全不相干的一个数据类型,则是危险和不合法的。、
  • ……

4)符号引用验证

  • 符号引用中通过字符串描述的全限定名是否能找到对应的类。
  • 在制定类中是否存在符合方法的字段描述符以及简单名称所描述的方法和字段。
  • 符号引用中的类、字段、方法的访问性(private、protected、public、default)是否可被当前类访问。
  • ……

3.准备

准备阶段是为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。

说明:这时候进行内存分配的仅包括类变量(静态变量,即被static修饰的变量),而不包括实际变量,实际变量将会在对象实例化时随着对象一起分配在Java堆中。

4.解析

虚拟机将常量池内的符号引用替换为直接引用的过程,符合引用在Class文件中以CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info等类型的常量出现。

♦ 符号引用(Symbolic References)

符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到内存中。各种虚拟机实现的内存布局可以不同,但是他们能接收的符号引用必须都是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中。

♦ 直接引用(Direct References)

直接引用可以是直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。直接引用是和虚拟机实现的内存布局相关的,同一个符号引用在不同虚拟机实例上翻译出来的直接引用一般不会相同。如果有了直接引用,那引用的目标必定已经在内存中存在。

5.初始化

执行类中定义的Java程序代码(或者说是字节码),初始化变量和其他资源。亦可以说是执行类构造器<clinit>()方法的过程。

转载于:https://www.cnblogs.com/justdoitba/articles/9126190.html

Java虚拟机笔记(一):类加载机制相关推荐

  1. Java虚拟机专题之类加载机制

    目录 一 类加载是什么?什么时候加载类?加载过程是怎么样的? 1.1 什么是类加载 1.2 类加载的时机 1.3 类加载过程 类的加载过程主要分为三个阶段: 加载.链接和初始化.1.3.1 加载 1. ...

  2. Java虚拟机笔记(五):JVM中对象的分代

    为什么要分代 为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用, ...

  3. 深入理解java虚拟机-笔记

    java内存区域与内存溢出异常 java虚拟机自动内存管理机制,不用像C/C++为每一个new操作去写配对delete/free代码 java虚拟机在执行java程序的过程中 会把内存划分为若干个不同 ...

  4. java 虚拟机类型的卸载_《深入理解Java虚拟机》:类加载和初始化(二)

    <深入理解Java虚拟机>:类加载和初始化(二) 在去年看<深入理解Java虚拟机>的时候,写过一篇关于类加载和初始化的博客,最近又在看这一块的知识,发现还是有很多东西没有理解 ...

  5. java虚拟机类加载机制_《深入理解java虚拟机》学习笔记一/类加载机制

    为何要读这本书? 近期看了左萧龙大哥的单例设计模式,后文讲解到了JVM对类实例化相关知识,感觉看着很无力,不懂,于是乎买本书研究下. 如何读? 个人水平一般,理解程度有限,书中说到每章关联不是很大,所 ...

  6. 《深入理解Java虚拟机》笔记5——类加载机制与字节码执行引擎

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

  7. 《深入理解Java虚拟机》内存管理机制 部分 读书笔记

    内存管理 运行时的数据区包括: 程序计数器 一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器. 每个下次都需要有一个独立的程序计数器,各线程间计数器互不影响,独立存储. 如果线程执行的 ...

  8. 深入学习Java虚拟机笔记

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.走进Java 1.4.2 HotSpot VM 1.4.4 BEA JRockit/IBM J9 VM 1.6.1 ...

  9. java学习笔记13--反射机制与动态代理

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...

最新文章

  1. RDKit | 基于RDKit绘制化学反应
  2. ORA-04031 错误
  3. python中str和int区别_Python中的string方法和str方法有什么区别?
  4. Hibernate.cfg.xml配置文件结构详解
  5. MySql 常用命令总结
  6. 求1+2+3+...(信息学奥赛一本通-T1158)
  7. Linux 配置vim编辑器
  8. docker教程_1 简介和安装
  9. atitit. orm mapping cfg 映射配置(3)-------hbnt one2maney cfg
  10. 《终极算法》阅读笔记与摘要(1)-序和第1-2章
  11. 小程序 跳转到腾讯文档小程序
  12. python 爬取图片、没有后缀名_python爬虫,图片是无格式的
  13. LUP分解的C++实现
  14. 精彩揭秘,一个高大上的机器人自动化工厂需要哪些标配?
  15. axios每次发送请求会有两次,多一次Request Method: OPTIONS是怎么回事?
  16. U3D中的常用字符串加密算法程序
  17. 阿里最伟大的计算机科学家,阿里两位科学家当选ACM2019年度杰出科学家
  18. 基于工作行为的研发管理体系设计及实践
  19. Java多态中的 向上转型/向下转型
  20. iSee图片专家 V3.8.7.3 圣诞贺岁版

热门文章

  1. Android报错——connect failed: EHOSTUNREACH (No route to host)
  2. iOS的相对路径和绝对路径
  3. Struts2中action获取request、response、session的方式
  4. Spring Roo 2 使用分析
  5. canvas三角函数模拟水波效果
  6. 【干货】前端自学之路(持续更新)
  7. BCH扩容的摩尔定律——为什么BCH目前不选择分片?
  8. Java基础学习总结(21)——数组
  9. OPPO R9s在哪里开启Usb调试模式的完美步骤
  10. 利用MingW检验程序运行内存