关于jvm:JVM学习之路4类文件结构及加载机制

3次阅读

共计 2056 个字符,预计需要花费 6 分钟才能阅读完成。

继上一篇 JVM 学习之路 3 -GC 机制和 GC 收集器剖析介绍完垃圾回收相干内容后,这篇说说类的加载机制。咱们平时在写代码的时候更多的是和对象打交道,很少去关怀类的相干信息是怎么来的,在之前的系列文章中咱们介绍过类信息是寄存在哪的、对象是如何找到本人的类等内容,都没有具体介绍过类是如何来的,它是怎么被加载到虚拟机里的。
知识点
1、类文件构造
2、虚拟机加载类机制

类文件构造

这里整顿了一幅图先做整体展现

下面图曾经对各个构造做了简略的阐明,字段表汇合是不蕴含办法的局部变量,这里再介绍一下常量池。

常量池

就是指字面量和符号援用,字面量即 java 语言层的常量概念,符号援用如:类和接口全限定名、字段办法名称和描述符等。每种常量项都有本人的一个表构造,具体能够再看一下书里的表,这里不再做援用。个别 java 用 Constant_utf8_info 项来存类名和办法名,所以咱们平时定义类和办法的时候不能过长(65535),当然个别也不会那么长。

虚拟机加载类机制

一个类从加载进虚拟机内存到从内存中卸载,整个生命周期如下:

加载、验证、筹备、初始化、卸载这五个阶段的程序是确定的,以下 6 种状况下必须先对类进行初始化:
1、遇到 new、getstatic、putstatic、invokestatic 指令,基本上就是 new 对象、静态方法调用和动态字段拜访。
2、反射调用。
3、父类没初始化过先做初始化。
4、虚拟机启动时执行主类要先初始化。
5、动静语言最终对应的办法动态调用须要先初始化。
6、有默认办法的接口要在类实例化前进行初始化。

加载

此阶段把类从文件的二进制流转换到办法区的运行时数据结构并生成 class 对象。除了从.class 文件中加载类信息,咱们还能够通过网络、zip 等压缩包、或者在代码中动静生成类信息。这里须要留神的是:数组类不是由类加载器加载,数组类如果放的是援用类型,该援用类型是由类加载器来加载,该数组类会被标识在该类加载器的类名称空间上,如果数组类放的不是援用类型,则会被标识在疏导类加载器上。

验证

这是连贯的第一个阶段,次要是为了保障加载的类字节流合乎虚拟机标准,避免恶意代码的侵入,爱护虚拟机的平安,为什么说 java 是类型平安的,这部分就是次要起因,次要有如下几局部校验:
1、文件格式校验,比方文件的魔数是否合乎定义。
2、元数据校验,对字节码形容的信息进行校验(看字节码:javap -verbose xxxClass),比方是否继承了不被容许继承的类。
3、字节码验证,通过数据流和控制流剖析来确保语义是非法的、合乎逻辑的。
4、合乎援用验证,产生在虚拟机将符号援用转换为间接援用时,比方查看是否短少依赖的内部办法、类等资源。

筹备

正式为类中的变量分配内存和设置初始值。举个例子:

public static int value = 123;

如上代码,在筹备阶段的时候会将 value 设置为 0,而不是 123,真正赋值 123 是在初始化阶段。当然如果是常量(用 final 润饰),则会间接初始化为 123。

解析

将常量池中符号援用替换为间接援用的过程,包含类 / 接口解析、办法解析、字段解析、接口办法解析等。
符号援用:就是一个字面量,比方类的全限定名,只有能惟一辨认该类就行,和内存布局无关。
间接援用:和内存布局相干,内存中要曾经存在该指标,间接援用相当于间接定位到该指标。

初始化

类加载过程的最初一个步骤,虚拟机将主导权交给应用程序。筹备阶段在分配内存和设置初始值之后,初始化阶段就会真正设置咱们赋予的初始值,就是在执行类结构器 <clinit>()办法的过程。动态语句块中只能拜访 到定义在动态语句块之前的变量,定义在它之后的变量,在后面的动态语句块能够赋值,然而不能拜访。

类加载器

在下面的加载机制中提到了类加载器,它除了能够加载类以外,还能够确认一个类在虚拟机中的唯一性(对于任意一个类,都必须由加载它的类加载器和这个类自身一起独特确立其在 Java 虚拟机中的唯一性),同一个类被同一个虚拟机加载,只有加载器不同,那类必然也不同。

双亲委派模式

java 虚拟机经典的双亲委派模式。一幅图:

启动类加载器(BootstrapClassLoader):负责加载寄存在 <JAVA_HOME>\lib 目录,或者被 -Xbootclasspath 参数所指定的门路中寄存的类到虚拟机中。
扩大类加载器(ExtClassLoader):负责加载 <JAVA_HOME>\lib\ext 目录中,或者被 java.ext.dirs 零碎变量所 指定的门路中所有的类库。
应用程序类加载器(AppClassLoader):负责加载用户类门路(ClassPath)上所有的类库。
根本机制:每当加载一个类的时候,虚构机会先用启动类加载器进行加载,加载不到再用扩大类加载器,再加载不到就用应用程序类加载器进行加载。这样能够保障一个类在虚拟机里惟一。

总结

本篇次要介绍了类文件构造以及类加载机制,整个类的加载过程还是比拟清晰且简略的,大家也能够本人试着定一个类加载器来加载类,跟进代码看一下双亲委派模式具体怎么走。

正文完
 0