JVM学习记录-类加载的过程

类的整个生命周期的7个阶段是:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading)。

类加载的全过程主要包括:加载、验证、准备、解析、初始化这5个阶段的内容。

加载

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

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

加载阶段(准确地说,是加载阶段获取类的二进制字节流的动作)是整个类加载过程中开发人员可控性最强的,因为加载阶段既可以使用系统提供的引导类加载器完成,又可以由用户自定义的二类加载器去完成,开发人员可以通过定义自己的类加载器区控制字节流的获取方式。

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

加载阶段与连接阶段的部分内容(如一部分字节码文件格式验证东西)是交叉进行的,但是这两个阶段的开始时间仍然保持着固定的 先后顺序。

验证

 验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。验证阶段是非常重要的,这个阶段是否严谨,直接决定了Java虚拟机是否能承受恶意代码的攻击,它大致上会完成4个阶段的检验工作:文件格式验证、元数据验证、字节码验证、符号引用验证。

文件格式验证

这一阶段主要验证字节流是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理。

验证内容包括:是否以魔数0xCAFEBABE开头,主次版本号是否在当前虚拟机处理范围之内,常量池的常量是否有不被支持的常量类型,指向常量的各种索引值是否有指向不存在的常量或不符合类型的常量,CONSTANT_Utf8_info型的常量中是否有不符合UTF8编码的数据,Class文件中各个部分及文件本身是否有被删除的或附近的其他信息等等。

元数据验证

第二阶段主要是对类的元数据信息进行语义校验,保证不存在不符合Java语言规范的元数据信息。

验证内容包括:当前类是否有父类(除了Object类之外,所有类都该有父类),当前类的父类是否继承了不被允许继承的类(被final修饰的类),如果当前类不是抽象类,是否实现了其父类或接口之中要求实现的所有方法,类中的字段、方法是否与父类产生矛盾(如覆盖了父类的final字段等)等等。

字节码验证

第三阶段是整个验证过程中最复杂的一个阶段,主要目的是通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。

验证内容包括:保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作,例如:保证不会出现在操作栈放置了一个int类型的数据,使用时却按long类型来加载如本地变量表中。保证跳转指令不会跳转到方法体以为的字节码指令上。保证方法体上的类型转换是有效的,例如:可以把一个子类对象赋值给父类数据类型,但是不能把父类对象赋值给子类数据类型。

符号引用验证

最后一个阶段的校验发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作发生在解析阶段。符号引用验证可以看做是对类自身以外的信息进行匹配校验。

验证内容包括:符号引用通过字符串描述的全限定明是否能找到对应的类。在指定类中是否存在符合方法的字段描述符以及简单名称所描述的方法和字段。符号引用中的类、字段、方法的访问性是否可以被当前类访问等等。

准备

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。这个阶段分配内存的仅仅是类变量不包括实例变量。实例变量实在对象实例化的时候分配在堆内存中的,还有就是这里给类变量设置的初始值“通常情况下”下是数据类型的零值,例如:

public static int value = 666;

 这个变量value的值在准备阶段被设置的初始值为0而不是666,因为此时尚未开始执行任何Java方法,而把value赋值为666的putstatic指令是程序编译后,存放于类构造器<clinit>()方法之中,所以把value赋值为666的动作将在初始化阶段才会执行。

上面说到在“通常情况”下初始值是零值,在非“通常情况”下也就是类字段属性中存在常量属性的时候,那么在准备阶段类变量就会被初始化为常量属性所指定的值。

public static final int value = 666;

编译时Javac将会生成常量属性,在准备阶段虚拟机就会根据常量属性的设置将value赋值为666;

解析

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。

符号引用(Symbolic References):符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局无关,引用目标并不一定已经加载到内存中。

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

解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符,这7类符号引用,分别对应于常量池的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_MethodHandle_info和CONSTANT_InvokeDynamic_info 这7中常量类型。

初始化

类初始化阶段是类加载过程的最后一步,前面的类加载过程中,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。在准备阶段,变量已经赋过一次系统初始零值了,而在初始化阶段,是通过程序制定的主观计划去初始化类变量和其他资源,也就是执行类构造器<clinit>()方法的过程。在上一篇“类的加载时机”中已经介绍过了,有5中情况会出发类初始化,下面介绍的是在<clinit>()方法执行过程中一些可能会影响程序运行行为的特点和细节。

  • <clinit>()方法是由编译器自动收集类中的所有类变量赋值动作和静态语句块(static{})中的语句合并产生的,编译器收集顺序室友语句在源文件中出现的竖线所决定的,静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面静态语句块可以赋值,但是不能访问。
  • <clinit>()方法与类的构造函数不同,它不需要显示的调用父类构造器,所以虚拟机中第一个被执行的<clinit>()方法的类肯定是java.lang.Object。
  • 由于父类的<clinit>()方法先执行,也就意味着福利中定义的静态语句块要由于子类的变量赋值操作。
  • <clinit>()方法对于类或接口来说并不是必需的,如果一个类中没有静态语句块,也没有对变量的赋值操作,那么编译器可以不为这个类生产<clinit>()方法。
  • 接口中不能使用静态语句块,但仍然有变量初始化的赋值操作,因此接口和类一样都会生成<clinit>()方法。接口中只有在使用父接口的时候才会初始化父接口(上一篇已经讲解过)。
  • 虚拟机会保证一个类的<clinit>()方法在多线程的环境中被正确地枷锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程区执行这个类的<clinit>()方法,其他线程都需要阻塞等待,直到活动线程<clinit>()方法

 

转载于:https://www.cnblogs.com/jimoer/p/9091315.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/280222.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 Azure CLI 将 IaaS 资源从经典部署模型迁移到 Azure Resource Manager 部署模型

以下步骤演示如何使用 Azure 命令行接口 (CLI) 命令将基础结构即服务 (IaaS) 资源从经典部署模型迁移到 Azure Resource Manager 部署模型。 本文中的操作需要 Azure CLI。 Note 此处描述的所有操作都是幂等的。 如果你遇到功能不受支持或配置错误以外的问题&#xff0c;建议你…

c++的进制转换函数

https://blog.csdn.net/u010003835/article/details/47665847https://blog.csdn.net/vir_lee/article/details/80645066strtol函数&#xff1a;用于由十进制转化到2~36的其他进制。函数原型为&#xff1a;long int strtol(const char *nptr,char **endptr,int base); 还应该注意…

黑苹果不能imessage_如何修复iMessage在iOS 10中不显示消息效果

黑苹果不能imessageiMessage got a huge update in iOS 10, adding things like third-party app integration, rich links, and a number of fun graphical effects for messages. If you’re seeing messages that say something like “(sent with Invisible Ink)” instead…

MyBatisPlus怎么忽略映射字段

TableField(exist false)&#xff1a;表示该属性不为数据库表字段&#xff0c;但又是必须使用的。 TableField(exist true)&#xff1a;表示该属性为数据库表字段。 Mybatis-Plus 插件有这个功能&#xff0c;可以看一下 TableName&#xff1a;数据库表相关 TableId&#xff1…

从技术总监到开源社区运营:过去两年,我都做了点啥?

这是头哥侃码的第267篇原创今天&#xff0c;这是我离开前公司的第 7 天。相信有不少吃瓜群众都很好奇&#xff0c;你这些天都在干啥&#xff1f;是不是蓬莱乐逍遥&#xff0c;过上了那悠闲的神仙日子&#xff1f;还是趁着疫情管控逐渐放开&#xff0c;和家人一起去深山老林里吸…

查看模拟器使用端口_为什么我们仍然使用模拟音频端口?

查看模拟器使用端口When leaks about what the chassis of the iPhone 7 might look like hit headlines earlier this week, technology columnists and industry analysts jumped on the chance to report that Apple’s next device may finally ditch its 3.5mm audio port…

ServletContextListener在Springboot中的使用

ServletContextListener是servlet容器中的一个API接口, 它用来监听ServletContext的生命周期&#xff0c;也就是相当于用来监听Web应用的生命周期。今天我们就来说说如何在Springboot 1.5.2这个轻量型框架中如何使用它。 其实配置ServletContextListener与其它Filter, Listener…

《ASP.NET Core 6框架揭秘》实例演示[34]:缓存整个响应内容

我们利用ASP.NET开发的大部分API都是为了对外提供资源&#xff0c;对于不易变化的资源内容&#xff0c;针对某个维度对其实施缓存可以很好地提供应用的性能。《内存缓存与分布式缓存的使用》介绍的两种缓存框架&#xff08;本地内存缓存和分布式缓存&#xff09;为我们提供了简…

常见端口介绍

Win常用端口 TCP端口&#xff08;静态端口&#xff09;TCP 0 ReservedTCP 1TCP Port Service MultiplexerTCP 2DeathTCP 5Remote Job Entry,yoyoTCP 7EchoTCP 11SkunTCP 12BomberTCP 16SkunTCP 17SkunTCP 18消息传输协议&#xff0c;skunTCP 19SkunTCP 20FTP Data,Amanda TCP 2…

如何更改Windows 10锁定屏幕超时

By default, Windows 10’s lock screen times out and switches off your monitor after one minute. If you’d like it to stick around longer than that–say, if you have background picture you like looking at or you enjoy having Cortana handy–there’s a simple…

ios 开发账号 退出协作_如何在iOS 10中的Notes上进行协作

ios 开发账号 退出协作iOS’ Notes app provides a convenient way to remember the great ideas you come up with and all the things you have to do. The app has evolved over the years, and iOS 10 adds even more features–including collaboration. iOS的Notes应用程…

poj 1182

食物链Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 86494 Accepted: 25887Description 动物王国中有三类动物A,B,C&#xff0c;这三类动物的食物链构成了有趣的环形。A吃B&#xff0c; B吃C&#xff0c;C吃A。 现有N个动物&#xff0c;以1&#xff0d;N编号。每…

条款6:若不想使用编译器自动生成的函数,就该明确拒绝

如果自己定义的类中并不需要copy assignment操作符或者copy构造函数&#xff0c;为了避免编译器自动生成因为编译器自动生成的没什么用&#xff0c;一般是按照顺序进行赋值或者拷贝&#xff0c;对于有对象内含有指针的话可能会出现一些问题可以在private中声明&#xff08;并不…

为什么Android Geeks购买Nexus设备

The Galaxy S III is the highest-selling Android phone, but much of the geeky buzz is around the Nexus 4 – and the Galaxy Nexus before it. Nexus devices are special because they don’t have some of Android’s biggest problems. Galaxy S III是最畅销的Android…

你的知识死角不能否定你的技术能力

有些事情你不知道&#xff0c;但你一定能解决。 有些人通过我账号资料里的微信加我&#xff0c;然后问我一些所谓“怎么办”的问题&#xff0c;不是我不告诉你&#xff0c;而是我确实不知道。我确实有很高的title&#xff0c;也确实有很多的技术积累&#xff0c;但我并没有达到…

算法练习(十二)

The Suspects Description 严重急性呼吸系统综合症( SARS), 一种原因不明的非典型性肺炎,从2003年3月中旬开始被认为是全球威胁。为了减少传播给别人的机会, 最好的策略是隔离可能的患者。 在Not-Spreading-Your-Sickness大学( NSYSU), 有许多学生团体。同一组的学生经常彼此相…

day4----函数-闭包-装饰器

day4----函数-闭包-装饰器 本文档内容&#xff1a; 1 python中三种名称空间和作用域 2 函数的使用 3 闭包 4 装饰器 一 python中三种名称空间和作用域 1.1名称空间&#xff1a; 当程序运行时&#xff0c;代码从上至下依次执行&#xff0c;它会将变量与值得关系存储在一个空间中…

滤波器和均衡器有什么区别_什么是均衡器,它如何工作?

滤波器和均衡器有什么区别It’s in your car, home theater system, phone, and audio player but it doesn’t have an instruction manual. It’s an equalizer, and with a little know-how you can tweak your audio and fall in love with it all over again. 它在您的汽车…

网络视频监控与人脸识别

明天又要去面试了&#xff0c;趁次机会也将以前做的东西总结一下&#xff0c;为以后理解提供方便&#xff0c;也再加深下印象。 网络视频监控与人脸识别主要由三个程序组成&#xff1a;1、视频采集与传输程序&#xff1b;2、接受与显示程序&#xff1b;3、人脸识别程序。下面就…

esxi.主机配置上联端口_为什么现代的电脑机箱仍然具有USB 2.0端口?

esxi.主机配置上联端口With USB 3.0 becoming more prevalent with each passing year now, you may have found yourself wondering why modern computers still have USB 2.0 ports built into them. With that in mind, today’s SuperUser Q&A post has the answers to…