当前位置: 首页 > 编程日记 > 正文

类加载过程中几个重点执行顺序整理

类的加载过程:

1、 JVM会先去方法区中找有没有相应类的.class存在。如果有,就直接使用;如果没有,则把相关类的.class加载到方法区

2、 在.class加载到方法区时,会分为两部分加载:先加载非静态内容,再加载静态内容

3、 加载非静态内容:把.class中的所有非静态内容加载到方法区下的非静态区域内

4、 加载静态内容:

4.1、把.class中的所有静态内容加载到方法区下的静态区域内

4.2、静态内容加载完成之后,对所有的静态变量进行默认初始化

4.3、所有的静态变量默认初始化完成之后,再进行显式初始化

4.4、当静态区域下的所有静态变量显式初始化完后,执行静态代码块

5,当静态区域下的静态代码块,执行完之后,整个类的加载就完成了。

6,如果存在继承关系,则父类先加载,再加载子类。

实例的初始化过程:

1、在堆内存中开辟一块空间

2、 给开辟空间分配一个地址

3、 把对象的所有非静态成员加载到所开辟的空间下

4、 所有的非静态成员加载完成之后,对所有非静态成员变量进行默认初始化

5、 所有非静态成员变量默认初始化完成之后,调用构造函数

6, 在构造函数入栈执行时,分为两部分:先执行构造函数中的隐式三步再执行构造函数中书写的代码

6.1、隐式三步:

1,执行super语句

2,对开辟空间下的所有非静态成员变量进行显式初始化

3,执行构造代码块

6.2、在隐式三步执行完之后,执行构造函数中书写的代码

7,在整个构造函数执行完并弹栈后,把空间分配的地址赋值给一个引用对象【注意是最后把地址值赋给栈中引用】

类的验证过程:

验证部分主要包含下面四个阶段的验证:

1. 文件格式的验证:

验证文件格式是否按照虚拟机的规范,也就是我们前面class文件结构中的内容,比如这是不是一个Class文件(看魔数,是否位CAFEBABE);

Java版本是否符合当前虚拟机的范围(Java可以向下兼容,但是不能处理大于当前版本的程序)等等。

2. 元数据的验证:

对Class文件中的元数据进行验证,是否存在不符合Java语义的元数据信息。这里有的朋友可能会比较疑惑,什么是元数据呢?一般情况下,一个文件中都数据和元数据。数据指的是实际数据,而元数据(Metadata)是用来描述       数据的数据。用过Java注解的朋友应该对元数据这种叫法并不陌生,对应的元注解,其实说的差不多都是一个意思。

举个例子:比如说我们定义了一个变量 int a = 1;可以理解成数据就是1,而元数据就是描述有一个字符串变量“a”,这个“a”的类型是int型的,它的值也是一个int型的1,这就是描述数据的数据,就是元数据。

3. 字节码的验证:

通过数据流和控制流分析,来确定程序语义是否合法。

以数据来说,要保证类型转换是有效的;对于控制流程的代码,不能让指令跳转到其它方法的字节码指令上等……

4. 符号引用的验证:

为了保证解析动作能正常完成,还需在虚拟机将符号引用转成直接引用的时候,判断其它要引用的类是否符合规定。比如,要引用的类是否能够被找到;引用的属性在对应类中是否存在,权限是否符合要求(private的是不能访问      的)等。

最后再说一点,验证阶段不是必须的,如果代码运行已经稳定了之后,可以通过设置参数-Xverfy:none参数来关闭类验证,减少虚拟机的类加载时间,提高运行效率。

类的解析过程:

解析阶段是将常量池中的符号引用替换为直接引用的过程。在进行解析之前需要对符号引用进行解析,不同虚拟机实现可以根据需要判断到底是在类被加载器加载的时候对常量池的符号引用进行解析(也就是初始化之前),还是等到一个符号引用被使用之前进行解析(也就是在初始化之后)。

到现在我们已经明白解析阶段的时机,那么还有一个问题是:如果一个符号引用进行多次解析请求,虚拟机中除了invokedynamic指令外,虚拟机可以对第一次解析的结果进行缓存(在运行时常量池中记录引用,并把常量标识为一解析状态),这样就避免了一个符号引用的多次解析。

解析动作主要针对的是类或者接口、字段、类方法、方法类型、方法句柄和调用点限定符7类符号引用。这里主要说明前四种的解析过程。

类或者接口解析

要把一个类或者接口的符号引用解析为直接引用,需要以下三个步骤:

1. 如果该符号引用不是一个数组类型,那么虚拟机将会把该符号代表的全限定名称传递给类加载器去加载这个类。这个过程由于涉及验证过程所以可能会触发其他相关类的加载2. 如果该符号引用是一个数组类型,并且该数组的元素类型是对象。我们知道符号引用是存在方法区的常量池中的,该符号引用的描述符会类似”[java/lang/Integer”的形式,将会按照上面的规则进行加载数组元素类型,如果描述符如前面假设的形式,需要加载的元素类型就是java.lang.Integer ,接着由虚拟机将会生成一个代表此数组对象的直接引用3. 如果上面的步骤都没有出现异常,那么该符号引用已经在虚拟机中产生了一个直接引用,但是在解析完成之前需要对符号引用进行验证,主要是确认当前调用这个符号引用的类是否具有访问权限,如果没有访问权限将抛出java.lang.IllegalAccess异常

字段解析

对字段的解析需要首先对其所属的类进行解析,因为字段是属于类的,只有在正确解析得到其类的正确的直接引用才能继续对字段的解析。对字段的解析主要包括以下几个步骤:

1. 如果该字段符号引用就包含了简单名称和字段描述符都与目标相匹配的字段,则返回这个字段的直接引用,解析结束2. 否则,如果在该符号的类实现了接口,将会按照继承关系从下往上递归搜索各个接口和它的父接口,如果在接口中包含了简单名称和字段描述符都与目标相匹配的字段,那么久直接返回这个字段的直接引用,解析结束3. 否则,如果该符号所在的类不是Object类的话,将会按照继承关系从下往上递归搜索其父类,如果在父类中包含了简单名称和字段描述符都相匹配的字段,那么直接返回这个字段的直接引用,解析结束4. 否则,解析失败,抛出java.lang.NoSuchFieldError异常

如果最终返回了这个字段的直接引用,就进行权限验证,如果发现不具备对字段的访问权限,将抛出java.lang.IllegalAccessError异常

类方法解析

进行类方法的解析仍然需要先解析此类方法的类,在正确解析之后需要进行如下的步骤:

1. 类方法和接口方法的符号引用是分开的,所以如果在类方法表中发现class_index(类中方法的符号引用)的索引是一个接口,那么会抛出java.lang.IncompatibleClassChangeError的异常2. 如果class_index的索引确实是一个类,那么在该类中查找是否有简单名称和描述符都与目标字段相匹配的方法,如果有的话就返回这个方法的直接引用,查找结束3. 否则,在该类的父类中递归查找是否具有简单名称和描述符都与目标字段相匹配的字段,如果有,则直接返回这个字段的直接引用,查找结束4. 否则,在这个类的接口以及它的父接口中递归查找,如果找到的话就说明这个方法是一个抽象类,查找结束,返回java.lang.AbstractMethodError异常5. 否则,查找失败,抛出java.lang.NoSuchMethodError异常

如果最终返回了直接引用,还需要对该符号引用进行权限验证,如果没有访问权限,就抛出java.lang.IllegalAccessError异常

接口方法解析

同类方法解析一样,也需要先解析出该方法的类或者接口的符号引用,如果解析成功,就进行下面的解析工作:

1. 如果在接口方法表中发现class_index的索引是一个类而不是一个接口,那么也会抛出java.lang.IncompatibleClassChangeError的异常2. 否则,在该接口方法的所属的接口中查找是否具有简单名称和描述符都与目标字段相匹配的方法,如果有的话就直接返回这个方法的直接引用。3. 否则,在该接口以及其父接口中查找,直到Object类,如果找到则直接返回这个方法的直接引用4. 否则,查找失败

接口的所有方法都是public,所以不存在访问权限问题

*************************************************************

类卸载过程分析:

类的生命周期

当Sample类被加载、连接和初始化后,它的生命周期就开始了。

当代表Sample类的Class对象不再被引用,即不可触及时,Class对象就会结束生命周期,Sample类在方法区内的数据也会被卸载,从而结束Sample类的生命周期。

由此可见,一个类何时结束生命周期,取决于代表它的Class对象何时结束生命周期。

引用关系

加载器和Class对象:双向引用

在类加载器的内部实现中,用一个Java集合来存放所加载类的引用。

另一方面,一个Class对象总是会引用它的类加载器。调用Class对象的getClassLoader()方法,就能获得它的类加载器。

由此可见,Class实例和加载它的加载器之间为双向关联关系。

类、类的Class对象、类的实例对象:单向引用

一个类的实例总是引用代表这个类的Class对象。

在Object类中定义了getClass()方法,这个方法返回代表对象所属类的Class对象的引用。

此外,所有的Java类都有一个静态属性class,它引用代表这个类的Class对象。

类的卸载

由Java虚拟机自带的类加载器所加载的类,在虚拟机的生命周期中,始终不会被卸载。

前面介绍过,Java虚拟机自带的类加载器包括根类加载器、扩展类加载器和系统类加载器。

Java虚拟机本身会始终引用这些类加载器,而这些类加载器则会始终引用它们所加载的类的Class对象,因此这些Class对象始终是可触及的。

由用户自定义的类加载器加载的类是可以被卸载的。

具体例子

oader1变量和obj变量间接应用代表Sample类的Class对象,而objClass变量则直接引用它。

如果程序运行过程中,将上图左侧三个引用变量都置为null,此时Sample对象结束生命周期,MyClassLoader对象结束生命周期,代表Sample类的Class对象也结束生命周期,Sample类在方法区内的二进制数据被卸载。

当再次有需要时,会检查Sample类的Class对象是否存在,如果存在会直接使用,不再重新加载;如果不存在Sample类会被重新加载,在Java虚拟机的堆区会生成一个新的代表Sample类的Class实例(可以通过哈希码查看是否是同一个实例)。

【总结】

(1) 启动类加载器加载的类型在整个运行期间是不可能被卸载的(jvm和jls规范);

(2) 被系统类加载器和标准扩展类加载器加载的类型在运行期间不太可能被卸载,因为系统类加载器实例或者标准扩展类的实例基本上在整个运行期间总能直接或者间接的访问的到,其达到unreachable的可能性极小。(当然,在虚拟机快退出的时候可以,因为不管ClassLoader实例或者Class(java.lang.Class)实例也都是在堆中存在,同样遵循垃圾收集的规则);

(3) 被开发者自定义的类加载器实例加载的类型只有在很简单的上下文环境中才能被卸载,而且一般还要借助于强制调用虚拟机的垃圾收集功能才可以做到.可以预想,稍微复杂点的应用场景中(尤其很多时候,用户在开发自定义类加载器实例的时候采用缓存的策略以提高系统性能),被加载的类型在运行期间也是几乎不太可能被卸载的(至少卸载的时间是不确定的)

综合以上三点, 一个已经加载的类型被卸载的几率很小至少被卸载的时间是不确定的。同时我们可以看的出来,开发者在开发代码时候,不应该对虚拟机的类型卸载做任何假设的前提下来实现系统中的特定功能。

转载于:https://www.cnblogs.com/gxyandwmm/p/9650144.html

相关文章:

二叉树 2.0 -- 非递归遍历

二叉树递归遍历存在的问题 如果我们的二叉树只有左子树,而且树的高度还很深的时候,这个时候递归调用遍历的时候,栈帧空间开辟的较大,很可能造成栈溢出。但是我们一个程序中,为堆分配的空间要比栈大的多,这…

田忌赛马贪心算法_田忌赛马 贪心算法

算法实验课回顾田忌赛马问题描述&#xff1a;你一定听说过田忌赛马的故事吧&#xff1f;如果3匹马变成n匹(n<100)&#xff0c;齐王仍然让他的马按照优到劣的顺序初赛&#xff0c;田忌可以按任意顺序选择他的赛马出赛。赢一局&#xff0c;田忌可以得到200两银子&#xff1b;输…

[转][小结][三种方法]实现WPF不规则窗体

实现WPF不规则窗体的三种常用的方法如下&#xff1a; 1.使用Blend等工具绘制一个不规则xaml&#xff0c;然后作为窗体的背景。这个可以参考xiaowei0705的这篇博文&#xff1a;WPF制作不规则的窗体 。 2.给window的Clip属性赋Path值。这个可以参考DebugLZQ前面的博文&#xff1a…

VirtualBox虚拟机网络连接设置的四种方式

这里我先给大家大致讲解下VBox的网络配置及应用。 VirtualBox的提供了四种网络接入模式&#xff0c;它们分别是&#xff1a;1、NAT 网络地址转换模式(NAT,Network Address Translation)2、Bridged Adapter 桥接模式3、Internal 内部网络模式4、Host-only Adapter 主机…

redis-deskmanager 连不上 虚拟机 - centos redis

1、没设置redis密码 &#xff1a; https://blog.csdn.net/HUXU981598436/article/details/54668779 2、关闭防火墙 转载于:https://www.cnblogs.com/Jomini/p/9650650.html

数据库1.0 -- 数据库的基本操作

安装数据库 安装数据库的时候我们需要安装三个软件&#xff0c;使用下面的命令&#xff0c;可能还会出现一些问题&#xff0c;关于数据库的安装&#xff0c;大家可以上网自行百度 yum install mysql yum install mysql-server yum install mysql-devel 我个人的理解大概是这…

12,缓冲运动。匀速运动停止条件

缓冲运动&#xff1a;iSpeed(iTarget-oDiv.offsetLeft)/7;速度离目标点越远&#xff0c;速度越大&#xff0c;离目标点越近速度越小&#xff1b; 只支持1px是最小单位&#xff0c;没有0.5px。所以当iSpeed为小数时如&#xff08;0.7&#xff09;&#xff0c;oDiv.style.LeftoDi…

如何配置mac的mysql环境_mac安装mysql数据库及配置环境变量

安装mysql下载mysql。我下载的是&#xff1a;mysql-8.0.11-macos10.13-x86_64.dmg双击打开mysql-8.0.11-macos10.13-x86_64.dmg&#xff0c;然后双击mysql-8.0.11-macos10.13-x86_64.pkg一路点击继续&#xff0c;傻瓜式安装&#xff0c;没什么好说的此处选择“Use Legacy Passw…

三层交换机vlan间访问(第一种方式)

真的是原创&#xff0c;但是得感谢Ys_routesim软件的制作方。我将命令调试后并进行了解释。若是属于侵权&#xff0c;请立即告知我。不过学习了网工后&#xff0c;大段解读源代码不属于侵权吧。呵呵。 交换机的三层交换实际是具有路由功能的交换机&#xff0c;比如思科的Cisco …

(转载)深入浅出设计模式——桥接模式(Bridge Pattern)

模式动机设想如果要绘制矩形、圆形、椭圆、正方形&#xff0c;我们至少需要4个形状类&#xff0c;但是如果绘制的图形需要具有不同的颜色&#xff0c;如红色、绿色、蓝色等&#xff0c;此时至少有如下两种设计方案&#xff1a; 第一种设计方案是为每一种形状都提供一套各种颜色…

数据库2.0 -- 数据类型和数据表的基本操作

mysql支持多种数据类型&#xff0c;一般可以分为&#xff0c;数值&#xff0c;日期时间和字符&#xff08;串&#xff09; 数值类型 日期和时间类型 字符串类型 创建数据表 我们首先应该明白的就是一个结构的问题&#xff0c;一个用户可以管理多个数据库&#xff0c;每个数据…

virtual hust 2013.6.20 数论基础题目 D - Just the Facts

题目&#xff1a;Just the Facts 思路&#xff1a;枚举10000素数内&#xff0c;各因子出现的次数&#xff0c;然后取模为10。因为0是由2和5构成的&#xff0c;所以2和5的幂单独讨论&#xff0c;同时由于2的幂肯定大于5的&#xff0c;所以我们最后要算的再乘上2的减去后的幂就可…

MySQL中字段约束有哪些_mysql字段约束

为了确保数据的完整性和唯⼀性&#xff0c;关系型数 据库通过约束机制来实现目。一. unique 唯一性约束值不可重复&#xff1b;二. not null 非空约束值不可为空&#xff1b;三. default 默认值约束当增加数据时没有插⼊值时&#xff0c;会自动插⼊默认值&#xff1b;四. chec…

关于软件测试中那点小事中的大道理

如果想让测试在公司的项目中发挥出它最大的价值&#xff0c;并不是招两个测试技术高手&#xff0c;或引入几个测试技术&#xff0c;而是测试技术对项目流 程的渗透&#xff0c;以及测试流程的改进与完善。虽然&#xff0c;当然测试行业前景乐观&#xff0c;许多中小企业也都在引…

每日一题 -- 11-1

一天十题选择&#xff0c;一天一道编程&#xff0c;一天一个面试题&#xff0c;一个一个剑指offer 排序是必须要掌握的一个算法&#xff0c;非常的重要 题目描述 有 n 个学生站成一排&#xff0c;每个学生有一个能力值&#xff0c;牛牛想从这 n 个学生中按照顺序选取 k 名学…

Java中? extends T和? super T的理解

? 通配符类型 - <? extends T> 表示类型的上界&#xff0c;表示参数化类型的可能是T 或是 T的子类; <? super T> 表示类型下界&#xff08;Java Core中叫超类型限定&#xff09;&#xff0c;表示参数化类型是此类型的超类型&#xff08;父类型&#xff09;&…

学习Modern UI for WPF

这两天断断续续的学了学Modern UI for WPF 没啥学习笔记呵呵&#xff0c;来自大牛王春明的博客园 http://www.cnblogs.com/wangchunming/category/342887.html 此大牛学习范围之广 成果之丰富 着实是学习的典范转载于:https://www.cnblogs.com/DragonX/p/3146818.html

idea的tomcat配置文件在哪里修改_MyBatis配置文件详解

MyBatis 的配置文件包含了会影响 MyBatis 行为的设置和属性信息&#xff0c;决定了mybatis的运行轨迹&#xff0c;能充分了解这些配置的以及配置所带来的的影响&#xff0c;你就是大神&#xff01;配置文件的根节点是configuration&#xff0c;他的子孙节点有&#xff1a;prope…

《几何与代数导引》例1.4——定比分点

点$r$分有向线段$\vec{pq}$成定比$k$,即$\vec{pr}k\vec{rq}(k\neq-1)$.在仿射标架中&#xff0c;已知$p(a_1,a_2,a_3)$,$q(b_1,b_2,b_3)$和$k$,求$r(c_1,c_2,c_3)$解:由于$c_i-a_ik(b_i-c_i)$,因此$c_i\frac{kb_ia_i}{1k}$.转载于:https://www.cnblogs.com/yeluqing/archive/20…

C#第一个程序Helloworld

转载于:https://www.cnblogs.com/gzhbk/p/9656149.html

Leanote

https://github.com/leanote/leanote/wiki/Leanote-%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B—-Mac-and-Linux 安装的网址 我们相当于是在本地建立了一个服务器&#xff0c;然后将我们的leanote部署上去了 我们这里的启…

微软安全新闻聚焦-双周刊第三十四期

Biweekly Spotlights 2013. 6. 5– 2013. 6. 20 第 34 期 微软发布 EMET 4.0 2013年6月17日 Enhanced Mitigation Experience Toolkit(EMET) 是微软提供的一个免费的攻击防御工具&#xff0c;它依托 Windows 系统本身的防御机制来阻止攻击者对各类…

mysql如何实现实时存储_OpenResty + Mysql 实现日志实时存储

应用场景和日志文件解析本配置主要解决 Nginx 向 MySQL 中实时插入日志的问题&#xff0c;采用 OpenResty Mysql 实现。1. 刚开始的时候看了 Nginx 和 MySQL 的连接模块。比如说 nginx-mysql-module&#xff0c;可以连接 MySQL。但是插入日志时遇到问题&#xff0c;我们知道 n…

简易RS232 建模二 (接收)

//clK系统时钟为50MHZ 先发低位后发高位 先接收地位后接收高位module uart_tx (input clk,rst_n, UART_CTS, output reg UART_RTS, input UART_RXD, output reg UART_TXD, output [7:0] led);reg [3:0]state;reg [30:0] count;reg [7:0] data;assign led rx_data; reg [7:0] …

《UNIX高级环境编程》 -- apue.h

在看《UNIX高级环境编程》这本书的时候&#xff0c;会遇到一个问题就是这个”apue.h”,这个是作者为了编写代码方便封装了一个库&#xff0c;我们可以使用下面的方式解决这个问题&#xff0c;让我们的代码可以像作者一样去使用&#xff0c;这样的话&#xff0c;我们就可以好好研…

mysql 多少个数据库_mysql数据库的几个基本概念

1、表数据库表是一系列二维数组的集合&#xff0c;用来存储数据和操作数据的逻辑结构。行是记录&#xff0c;列是字段&#xff0c;每一列表示记录的一个属性&#xff0c;都有相应的描述信息。2、数据类型&#xff1a;数据类型决定了数据在计算机中的存储格式&#xff0c;代表不…

教孩子正确对待分数

期末考试各科成绩渐渐公布了&#xff0c;小丽迫不及待地跑到办公室向老师打听分数。看到自己那一科成绩好时欣喜若狂&#xff0c;看到差的则懊悔不已。如果你的孩子也象小丽一样视考分为命根&#xff0c;该如何教孩子正确对待分数?让她从考分的困惑中解放出来?●考前给孩子制…

canvas初尝试

最近学习了canvas&#xff0c;就拿它做了这么个小东西&#xff0c;感觉已经爱上canvas了。上代码 /* * auhor : 开发部-前端组-李鑫超 * property { tableData : {Array} 表格数据 add v-1.0.0 } * property { columData : {Array} 表头数据 add v-1.0.0 } * property { me…

模板1.0 -- 模板基本原理

为什么需要模板 我们经常有这样的一种使用的情形&#xff0c;就是我们可能需要设计一个函数&#xff0c;然后函数的参数可能是整形的&#xff0c;也可能是浮点型的&#xff0c;还有可能是其他的类型的&#xff0c;这个时候如果对于每一个类型都写一个函数&#xff0c;未免有点…

[置顶] 我的GB28181标准开发里程碑——基于eXosip的IPC端与SPVMN注册成功

昨天编译搭建好eXosip的开发环境后&#xff0c;今天完成了SIP注册功能&#xff0c;里程碑一战啊&#xff01;加油加油&#xff0c;成功就在眼前&#xff01; 今天基于eXosip做了一个IPC客户端&#xff0c;成功与公安部的SPVMN视频监控联网调测软件自测工具进行注册交互&#xf…