文档章节

虚拟机类加载机制概叙2:类加载的过程

玄影镜心
 玄影镜心
发布于 2015/06/17 12:33
字数 1456
阅读 17
收藏 0

本篇将逐一描述类加载的过程中,加载、验证、准备、解析、初始化各个阶段的动作。

一:加载

    ⑴:类的加载

    类的加载阶段,虚拟机需要完成3件事:

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

    2:(结构转换)将字节流的静态存储结构 转换成方法区的运行时    

    3:(生成对象)在内存中生成一个代表此类的Class对象,作为方法区此类的数据访问入口。

注意:第一条并没有明确要求二进制字节流的获取途径,它可是一一个class文件,也可以是jar包、网络获取、运行时计算生成等等,非常灵活。

    ⑵:数组的加载

    数组本身不通过类加载器来创建,他由java虚拟机直接创建。但是数组类的元素类型(去掉所有维度的最终类型)需要靠类加载器创建。

    如果数组的组件类型(去掉一个维度的类型)是引用类:递归采用类的加载过程(上面)去加载这个组件。

    如果数组组件不是引用类,java虚拟机会把数组标记与引导类加载器关联。

    可见性:数组的可见性与他的组件类型的可见性一致,如果组件不是引用类型,那么默认public.

    ⑶:加载完成

    加载完成后,虚拟机外部的二进制字节流就按照虚拟机要求的格式存储在方法区,方法区中的数据存储结构是由虚拟机实现自定义的。

二:验证

    验证的目的:确保二进制字节流所包含的信息符合当前虚拟机的要求,且不会危害虚拟机自身安全。所以这个阶段非常重要。

    验证阶段可以分为4个阶段的检验动作:文件格式验证、元数据验证、字节码验证、符号引用验证。

    四个阶段所验证的校验对象大约可以对应为:文件格式----元数据----方法----类本身以外的信息

    1:文件格式验证:验证字节流是否符合class文件格式的规范,并且能被当前版本的虚拟机理解。(比如魔术、主次版本号、常量池中常量类型等等【很多】)

    2:元数据验证对字节码描述信息进行语义分析,确保其描述的信息符合java语言规范。(如验证是否有父类、这个父类是否允许继承等等)

    3:字节码验证:这个阶段对类的方法进行校验,通过数据流和控制流分析,以确定程序语义是合法的、符合逻辑的。(最复杂的验证阶段)

    4:符号引用验证:发生在虚拟机将符号引用转换为直接引用的时候,这个动作在连接的第三个阶段(解析阶段)中发生。可以看作是对类自身以外的信息(常量池中的各种符号引用)进行匹配校验

    说明:只有通过文件格式验证后,字节流才会进入内存的方法区存储,而后面的3个验证阶段,全部都是基于方法区存储结构进行的,不会在操作字节流。

三:准备

    此阶段将会正式在方法区中为类变量 分配内存 并设置变量的初始值

    注意:1:进行内存分配的仅包括类变量,不含实例变量(实例变量是在对象实例化时,同对象一起分配在java堆中)

              2:设置类变量的初始值,是指数据类型类型的初始值,而不是代码中设定的值(如int默认0 ,double默认0.0d)。

              3:如果类的字段属性表中存在ConstantsValue属性,那么准备阶段变量value就会被初始化为ConstantsValue属性所指定的值。(例如:准备阶段会给常量直接赋最终值)

四:解析

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

    (略)

五:初始化

    初始化阶段开始真正执行java程序中的代码(字节码),此阶段会根据代码中制定的计划去初始化变量和其他资源

    初始化阶段是执行类构造器<clinit>()方法的过程。

    <clinit>()方法是由编译器自动收集类中的“所有类变量的赋值动作”和“静态语句块中的语句”来合并产生的。换句话说<clinit>()方法对一个类或者接口来说,并不是必需的。如果一个类没有静态语句块,也没有对变量的复制操作,那么编译器不会对这个类生成<clinit>()方法。

    <clinit>()不需要显示的调用父类构造器,虚拟机会保证在调用子类<clinit>()之前,父类的<clinit>()方法已经执行完毕。(这意味着:父类中的静态语句块要优先于子类中的变量赋值操作)

    值得注意的是:虚拟机会保证一个类的<clinit>()方法在多线程环境下被正确的加锁、同步,如果有多个线程同时去初始化一个类,那么最终只能有一个线程去执行这个类的<clinit>()方法,其他线程都将阻塞。但是通一个类加载器下,一个类只会被初始化一次,也就是说当这个类执行完<clinit>()方法后,其他线程在被唤醒后并不会再次进入<clinit>()方法。



© 著作权归作者所有

共有 人打赏支持
玄影镜心
粉丝 9
博文 90
码字总数 49460
作品 0
西安
高级程序员
私信 提问
让类活起来——漫谈JVM类加载机制

所谓类加载机制,就是虚拟机把描述类的数据从Class文件加载到内存中,并对其进行校验,转换,分析以及初始化,并最终形成虚拟机可以被使用java类型的过程。 Java作为解释型语言,支持动态加载...

登高且赋
01/09
0
0
Android 简单热修复(上)——Java类加载器

作为阳历新年的第一篇文章,本想把之前总结的用到实践中,简单写了个钟表,写着写着感觉索然无味(/ □ )。写完后,百无聊赖之际,随便翻看了些技术文章。让我眼前为之一亮的有两个: Androi...

nick_young
01/05
0
0
[总结]-第七章 虚拟机类加载机制

[总结]-第七章 虚拟机类加载机制 常见操作 1、查看class二进制内容 2、打印类加载信息 3、关闭类加载过程中的大部分类验证措施 定义 1、类加载器: 将“通过一个类的全限定名来获取描述此类的...

GMarshal
08/16
0
0
Java虚拟机加载类文件大全-精细版

java加载类文件精细版,请仔细看 Java技术提供三种确保安全机制 语言设计特性 (对数组的边界进行检查、类型转换检查、无指针算法) 安全的访问控制机制 代码签名 类加载器 先看一下虚拟机执...

奔跑的蛙牛
08/22
0
0
Java类加载机制(一)

类加载机制 类加载过程 加载 将class文件字节码内容加载到内存中,并将这些静态数据转换为方法区的运行 时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为 方法区类数据访问...

wjk_snail
2016/01/16
113
0

没有更多内容

加载失败,请刷新页面

加载更多

EOS账户如何工作,我们如何获取eos账号?

EOS账户的工作方式是什么?帐户是存储在区块链中的人类可读名称。它可以由个人或一群人拥有,具体的取决于权限配置。需要一个帐户来将交易转移或推送到区块链。——EOSIO Wiki EOS账户如何工...

笔阁
2分钟前
0
0
iOS面试之@property

https://juejin.im/post/5c105c7ce51d4562d138086f @property介绍 相信做过iOS开发的同学都使用过@property,@property翻译过来是属性。在定义一个类时,常常会有多个@property,有了@proper...

壹峰
3分钟前
0
0
[springBoot系列]--springBoot注解大全

一、注解(annotations)列表 @SpringBootApplication:包含了@ComponentScan、@Configuration和@EnableAutoConfiguration注解。其中@ComponentScan让spring Boot扫描到Configuration类并把它加......

Jack088
17分钟前
3
0
tomcat编译超过64k大小的jsp文件报错原因

  今天遇到一个问题,首先是在tomcat中间件上跑的web项目,一个jsp文件,因为代码行数实在是太多了,更新了几个版本之后编译报错了,页面打开都是报500的错误,500的报错,知道http协议返回...

SEOwhywhy
39分钟前
5
0
flutter http 请求客户端

1、pubspec文件管理Flutter应用程序的assets(资源,如图片、package等)。 在pubspec.yaml中,通过网址“https://pub.dartlang.org/packages/http#-installing-tab-”确认版本号后,将http(0...

渣渣曦
39分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部