文档章节

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

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

码上生花,ECharts 作品展示赛正式启动!>>>

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

一:加载

    ⑴:类的加载

    类的加载阶段,虚拟机需要完成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
博文 117
码字总数 60509
作品 0
西安
程序员
私信 提问
加载中
请先登录后再评论。
java虚拟机05-虚拟机加载类机制&类加载器

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

osc_vgepqglw
2019/05/09
2
0
Java开发基础知识之学习篇——类加载机制

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

osc_9yc7q9oq
03/08
2
0
Java 对象的创建以及类加载

1.  对象的创建的过程:    类加载检查—>分配内存—>初始化零值—>设置对象头—>执行 init 。    1.类加载检查: 虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常...

osc_2hu29vz2
2019/04/01
3
0
让类活起来——漫谈JVM类加载机制

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

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

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

nick_young
2018/01/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Beta冲刺--Day2

2020/05/29 这个作业属于哪个课程 2020春S班软件工程实践 这个作业要求在哪里 团队作业第六次——beta冲刺+事后诸葛亮 团队名称 云玩家$ 这个作业的目标 beta冲刺,测试和完善已有的项目 作业...

osc_taer599u
今天
15
0
题解 [SDOI2010]猪国杀

题目链接 代码成功卡到600行以内 曾经发誓一天切掉的我打了两周。。。 先看题 要点还是挺多的,即使是像我这样熟悉三国杀的同(wán)学( jiā),也要认真看。 首先是基本牌的部分。 杀:在...

osc_4p2c0ecc
今天
17
0
Beta冲刺--Day3

2020/05/30 这个作业属于哪个课程 2020春S班软件工程实践 这个作业要求在哪里 团队作业第六次——beta冲刺+事后诸葛亮 团队名称 云玩家$ 这个作业的目标 beta冲刺,测试和完善已有的项目 作业...

osc_sejhgcp0
今天
23
0
vue3.0提前了解系列----一些普通用法和api的使用

今天给大家说说vue3.0 composition api里面一些剩余的普通api的使用 provide & inject provide和inject用于在一些高阶组件中常用,在2.x中也有一样的api那么在compositionapi中怎么用呢? 仅...

osc_kvcz9ju6
今天
5
0
Beta冲刺--Day4

2020/05/31 这个作业属于哪个课程 2020春S班软件工程实践 这个作业要求在哪里 团队作业第六次——beta冲刺+事后诸葛亮 团队名称 云玩家$ 这个作业的目标 beta冲刺,测试和完善已有的项目 作业...

osc_ze3jj3wd
今天
26
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部