栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

深入理解虚拟机-虚拟机加载机制

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

深入理解虚拟机-虚拟机加载机制

虚拟机类加载机制

文章目录
  • 虚拟机类加载机制
    • 类加载机制
    • 类加载时机
    • 接口的加载过程和类的加载过程的不同
    • 加载阶段
    • 验证
      • 文件格式验证
      • 元数据验证
      • 字节码验证
      • 符号引用验证
    • 准备
    • 解析
    • 初始化
    • 类加载器
    • 双亲委派模式

类加载机制

java虚拟机将Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称为虚拟机的类加载机制。

类型的加载,链接和初始化过程都是在程序运行期间完成的,

类加载时机

生命周期
加载 验证 准备 解析 初始化 使用 卸载
这些阶段通常交叉的混合进行。

解析和初始话阶段可能调换,为了支持java运行时绑定。

加载的实际由虚拟机具体实现来自由把握

规定了必须初始化的六种情况:
1,遇到new,getstatic,putstatic,invokestatic这四条字节码时,没初始化,必须先初始化。常见场景:
(1)使用new关键字实例化
(2)读取或设置一个类型的静态字段(被final修饰,已经在编译时期将结果放入常量池的静态字段 除外
(3)调用一个类型的静态方法时
2,反射调用时
3,初始化子类 发现父类还没初始化时
4,虚拟机启动时 执行的主类需要先实例化
5,jdk7新接入的动态语言支持 如果javv.lang.invoke.MethodHandle 实例最后的解析结果是REF_getStatic,REF_putStatic,REF_invokeStatic,REF_newInvokeSpecial四种类型方法的句柄,并且方法句柄对应的类没有进行过初始化,则需要先初始化
6,当接口中定义了jdk8新加入的默认方法是,如果该接口的实现类被实例化,那接口要在其之前初始化
以上引用方式被称为主动引用。
除此之外的引用都不会引发初始化,称为被动引用。

接口的加载过程和类的加载过程的不同

一个类初始化时,要求父类全部初始化过了,但一个接口初始化时,并不要求父类初始化,

加载阶段

java虚拟机需要完成三个事情:
1,通过类的全限定名来获取定义此类的二进制流
2,将这个字节流所代表的静态存储数据转化为方法区的运行数据结构
3,在Java堆内存中创建代表这个类的java.lang.class对象,作为方法区的各种数据的访问入口,

数组类本身不通过java类加载器创建,它是由java虚拟机直接在内存中动态创建。但数组去掉所有维度的元素类型,还是依靠类加载器实现。

数组类的创建遵循以下过程:
1,如果数组的组件类型(去掉一个维度的类型,)是引用类型,则递归采用上述的加载过程。
2,如果数组的组件不是引用类型(如 int)java虚拟机会将数组标记为和引导类加载器关联
3,数组类的可访问性与它的组件访问性一致。

验证

这一阶段的目的是确保Class类的信息符合java虚拟机规范的全部约束要求,
主要有四个阶段的验证动作:

文件格式验证

1,是否以魔数开头
2,主次版本号
3,常量池引用是否存在 是否正常
4,编码是否规范
5,文件各部分是否有被删除的

元数据验证

对字节码描述信息进行语义分析
1,类是否有父类(object除外)
2,是否继承final类
3,非抽象类 是否实现了父类和接口的所有要i求实现的方法

字节码验证

主要通过数据流分析和控制流分析,确定语义是否合法,符合逻辑。对类的方法体(class文件的code属性)进行校验分析。
1,保证调用int 就是int
2,跳转指令不跳出方法体外
3,保证类型转换有效

为了节约时间,jdk6以后把校验辅助放置在javac编译器里实现,给方法体Code属性的属性表增加一项名为“StackMapTable"的新属性, java验证阶段 检查该属性即可。

符号引用验证

在解析阶段发生,当虚拟机将符号引用转为直接引用的时候,可以理解为对类自身以外的各类信息进行匹配校验,就是该类是否缺少依赖,或者依赖不可访问。

准备

正式为类中定义的变量(静态变量)分配内存并设置变量的初始值,逻辑上这些变量应存在方法区。
实例变量则是在实列话时赋值
如果静态变量被final修饰 则此时赋值不是初始值,而是定义的值。

解析

是将java虚拟机的符号引用转换为直接引用的过程,
符号引用:与内存布局无关的,是class文件中明确定义的
直接引用:直接指向目标的指针,相对偏移量或者一个能间接定位到目标的句柄。使用直接引用 意味着内存已经存在该目标

对一个目标的解析可以缓存 避免重复解析 除了动态调用限定符

初始化

初始化阶段主要是执行类构造器()方法,就是根据程序员的程序编码初始化实例变量和其他资源。

类加载器

通过一个类的全限定名来获得描述该类的二进制流,这个动作放到Java虚拟机外部实现,实现这个的动作的代码被称为”类加载器“

只有同一个类加载器加载的 同一个class文件 才有可能相同。

双亲委派模式

在java虚拟机的角度来看,只存在:一种启动类加载器,是虚拟机的一部分,一种是其他所有类的加载器,这些类加载器都独立于虚拟机外;
但java开发人员看来分得更细致一些,jdk1.2以来主要保持着三层类加载器,
双亲委派架构:
1,启动类加载器:这个类负责加载llib 目录或者被-Xbootclasspath指定的路径中存放的,而且是java虚拟机能识别的类库加载到虚拟机内存中
2,扩展类加载器:以java代码的形式存在 负责加载libext 目录中的,或被java.ext.dirs 系统变量所指定的路径中所有的类库,是java系统类库的扩展机制,后来被模块化的天然扩展机制能力所取代。
3.应用程序类加载器:别称 系统类加载器 它负责加载用户路径上的所有类库,开发者同样可以在代码中直接使用。

各种类加载器的层次关系被称为双亲委派模型,该模型要求除了启动类的加载器,都应有自己的父类加载器,并不是通过继承实现,而是通过组合服用父类代码。
一个加载器收到一个类加载请求,它会向父类加载器请求,当父类加载器不行时,才会自己尝试。因此java中的类具有层次关系,你创建的object类不会影响java程序的object类

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1040933.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号