文档章节

虚拟机类加载机制概叙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>()方法。



© 著作权归作者所有

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

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

nick_young
01/05
0
0
让类活起来——漫谈JVM类加载机制

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

登高且赋
01/09
0
0
Java类加载机制(一)

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

wjk_snail
2016/01/16
113
0
JVM 类加载机制

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

zzzzzga
2017/08/06
0
0
深入理解Java虚拟机——JVM类加载机制(类加载过程和类加载器)

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

SilenceOO
2017/09/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

1、Vue解决安卓4.4不兼容的问题

1.npm安装 npm install babel-polyfill--save-devnpm install es6-promise--save-dev package.json中会出现 "babel-polyfill": "^6.26.0","es6-promise": "^4.1.1", 2.main.js引入 impo......

阿K1225
8分钟前
0
0
mybatis generator 属性详解

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis......

太黑_thj
12分钟前
0
0
windows nvm 安装 node

nvm 是 node 的版本控制管理 下面是下载 nvm 的地址,选择 nvm-setup.zip 下载 https://github.com/coreybutler/nvm-windows/releases 就是下一步下一步,一键安装 基本命令有: nvm arch [32...

U_I_A_N
14分钟前
0
0
js判断字符串中是否包含某个字符串

indexOf() indexof()方法可以返回某个指定的字符串值在字符串中首次出现的位置。如果要检索的字符串值没有出现,则该方法返回-1。 var str = "123";console.log(str.indexOf("3") != -1);...

小星星_cjx
26分钟前
0
0
函数式组件完整例子

之前创建的组件是比较简单,没有管理或者监听任何传递给他的状态,也没有生命周期方法。它只是一个接收参数的函数。 在下面这个例子中,我们标记组件为 functional,这意味它是无状态 (没有响...

tianyawhl
29分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部