文档章节

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

玄影镜心
 玄影镜心
发布于 2015/06/17 12:33
字数 1456
阅读 17
收藏 0
点赞 0
评论 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>()方法。



© 著作权归作者所有

共有 人打赏支持
玄影镜心
粉丝 8
博文 72
码字总数 49460
作品 0
西安
高级程序员
Android 简单热修复(上)——Java类加载器

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

nick_young ⋅ 01/05 ⋅ 0

让类活起来——漫谈JVM类加载机制

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

登高且赋 ⋅ 01/09 ⋅ 0

Class文件的加载过程

在class文件中描述的各种信息,最终都需要被加载到虚拟机中之后,才能被运行和使用。 虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验,转换,解析和初始化,最终形成可以被虚...

LCZ777 ⋅ 2014/08/05 ⋅ 0

Java类加载机制(一)

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

wjk_snail ⋅ 2016/01/16 ⋅ 0

虚拟机类加载机制

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

无聊书生 ⋅ 2015/08/13 ⋅ 0

JVM 类加载机制

一、为什么要使用类加载器? Java语言里,类加载都是在程序运行期间完成的,这种策略虽然会令类加载时稍微增加一些性能开销,但是会给java应用程序提供高度的灵活性。例如: 1.编写一个面向接...

zzzzzga ⋅ 2017/08/06 ⋅ 0

深入理解Java虚拟机——JVM类加载机制(类加载过程和类加载器)

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

SilenceOO ⋅ 2017/09/07 ⋅ 0

tomcat学习笔记

第一章 JVM原理 一、什么是JVM JVM是Java Virtual Machine(Java虚拟机)的缩写。 JAVA语言的平台无关性如何实现:通过Java虚拟机,Java语言在不同平台上运行时不需要重新编译。Java语言使用...

123654zf ⋅ 2017/07/05 ⋅ 0

Java基础-Java编译详解

Java基础-Java编译详解 Java源代码编译过程 Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示: Java代码编译和执行的整个过...

xjt2016 ⋅ 2016/12/27 ⋅ 0

ClassLoader和类加载机制

1、背景 最近在做项目的过程中,由于系统需要提供一个对外接口,使系统使用者可以以脚本的形式提交自己的代码,每个用户可以在系统规范的约束下编写脚本,由系统去执行用户的代码,实现了热部...

戬杨Jason ⋅ 2017/08/01 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

R计算IV

参考文章 #读取文件 rawdata = read.csv("/path/to/csv/file",header=T) colnames(rawdata)[18] <- "y" //重命名因变量y #数据分区 训练集测试集 trainIdx <- sample(nrow(rawdata), round(......

火力全開 ⋅ 5分钟前 ⋅ 0

SQL老司机,在SQL中计算 array & map & json数据

摘要: 场景 通常,我们处理数据,一列数据类型要么是字符串,要么是数字,这些都是primitive类型的数据。 场景 通常,我们处理数据,一列数据类型要么是字符串,要么是数字,这些都是primi...

阿里云云栖社区 ⋅ 5分钟前 ⋅ 0

SQL老司机,在SQL中计算 array & map & json数据

摘要: 场景 通常,我们处理数据,一列数据类型要么是字符串,要么是数字,这些都是primitive类型的数据。 场景 通常,我们处理数据,一列数据类型要么是字符串,要么是数字,这些都是primi...

猫耳m ⋅ 16分钟前 ⋅ 0

关于ireport自定义变量类型为list的时候

自己摸石头过河,我真的应该去趟市中心图书馆,借本真正靠谱的教材 网上的东西,只有0.01%是有用的,还有0.99%是垃圾,剩下的99%是垃圾的复制品。。 哎!~ 问题是这样的,报表带sql,从db中获...

炑炑milina ⋅ 17分钟前 ⋅ 0

Spring mvc ContextLoaderListener 原理解析

对于熟悉Spring MVC功能,首先应从web.xml 开始,在web.xml 文件中我们需要配置一个监听器 ContextLoaderListener,如下。 <!-- 加载spring上下文信息,最主要的功能是解析applicationContex...

轨迹_ ⋅ 17分钟前 ⋅ 0

阿里云发布企业数字化及上云外包平台服务:阿里云众包平台

摘要: 阿里云正式发布旗下众包平台业务(网址:https://zhongbao.aliyun.com/),支持包括:网站定制开发,APP、电商系统等软件开发,商标、商品LOGO、VI、产品包装设计、营销推广、大数据人...

阿里云官方博客 ⋅ 19分钟前 ⋅ 0

Redis安装异常解决办法

官网地址:http://redis.io/ 官网下载地址:http://redis.io/download 1. 下载Redis源码(tar.gz),并上传到Linux 2. 解压缩包:tar zxvf redis-2.8.17.tar.gz 3. 进入解压缩后的文件夹:c...

slagga ⋅ 23分钟前 ⋅ 0

006. 深入JVM学习—年轻代

1. 年轻代图片 年轻代(Young)属于JVM堆内存空间的一个组成部分 所有使用关键字new新实例化的对象一定会在伊甸园区进行保存,而对于存活区保存的一定是已经在伊甸园区存在一段时间并且经过了...

影狼 ⋅ 24分钟前 ⋅ 0

如何成为一个合格的程序员

偶尔的,我会被人问道:如何成为一名优秀的程序员,更或者,如何成为一名程序员。每次人们问起,我都力图给出不同的答案。因此,我的答案是各种各样的。下面就是我认为的成为一名优秀的程序员...

柳猫 ⋅ 25分钟前 ⋅ 0

cups error_log日志暴增

日志内容 File \"/usr/lib/cups/notifier/dbus\" has insecure permissions 解决(未验证适用范围) sudo service cups stopsudo rm /etc/cups/subscriptions.conf*sudo rm -r /var/cac......

一介码夫_Hum ⋅ 29分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部