一、类的加载过程

JVM将类的加载分为3个步骤:

1、装载(Load)

2、链接(Link)

3、初始化(Initialize)

其中 链接(Link)又分3个步骤,如下图所示:

1) 装载:查找并加载类的二进制数据(查找和导入Class文件)

加载是类加载过程的第一个阶段,在加载阶段,虚拟机需要完成以下三件事情:

1、通过一个类的全限定名来获取其定义的二进制字节流。

2、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

3、在Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口。

相对于类加载的其他阶段而言,加载阶段(准确地说,是加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,因为开发人员既可以使用系统提供的类加载器来完成加载,也可以自定义自己的类加载器来完成加载。

加载阶段完成后,虚拟机外部的 二进制字节流就按照虚拟机所需的格式存储在方法区之中,而且在Java堆中也创建一个java.lang.Class类的对象,这样便可以通过该对象访问方法区中的这些数据。

2) 链接(分3个步骤)

1、验证:确保被加载的类的正确性

验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。验证阶段大致会完成4个阶段的检验动作:

文件格式验证:验证字节流是否符合Class文件格式的规范;例如:是否以0xCAFEBABE开头、主次版本号是否在当前虚拟机的处理范围之内、常量池中的常量是否有不被支持的类型。

元数据验证:对字节码描述的信息进行语义分析(注意:对比javac编译阶段的语义分析),以保证其描述的信息符合Java语言规范的要求;例如:这个类是否有父类,除了java.lang.Object之外。

字节码验证:通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。

符号引用验证:确保解析动作能正确执行。

验证阶段是非常重要的,但不是必须的,它对程序运行期没有影响,如果所引用的类经过反复验证,那么可以考虑采用-Xverifynone参数来关闭大部分的类验证措施,以缩短虚拟机类加载的时间。

2、准备:为类的静态变量分配内存,并将其初始化为默认值

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中分配。对于该阶段有以下几点需要注意:

1、这时候进行内存分配的仅包括类变量(static),而不包括实例变量,实例变量会在对象实例化时随着对象一块分配在Java堆中。

2、这里所设置的初始值通常情况下是数据类型默认的零值(如0、0L、null、false等),而不是被在Java代码中被显式地赋予的值。

假设一个类变量的定义为:public static int value = 3; 那么变量value在准备阶段过后的初始值为0,而不是3,因为这时候尚未开始执行任何Java方法,而把value赋值为3的putstatic指令是在程序编译后,存放于类构造器<clinit>()方法之中的,所以把value赋值为3的动作将在初始化阶段才会执行。

3、解析:把类中的符号引用转换为直接引用

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用限定符7类符号引用进行。符号引用就是一组符号来描述目标,可以是任何字面量。
直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。

3) 初始化:对类的静态变量,静态代码块执行初始化操作

初始化,为类的静态变量赋予正确的初始值,JVM负责对类进行初始化,主要对类变量进行初始化。在Java中对类变量进行初始值设定有两种方式:

①声明类变量是指定初始值。

②使用静态代码块为类变量指定初始值。

类的初始化

类什么时候才被初始化:

1)创建类的实例,也就是new一个对象

2)访问某个类或接口的静态变量,或者对该静态变量赋值

3)调用类的静态方法

4)反射(Class.forName("com.lyj.load"))

5)初始化一个类的子类(会首先初始化子类的父类)

6)JVM启动时标明的启动类,即文件名和类名相同的那个类 只有这6中情况才会导致类的类的初始化。

类的初始化步骤 / JVM初始化步骤:

1)如果这个类还没有被加载和链接,那先进行加载和链接

2)假如这个类存在直接父类,并且这个类还没有被初始化(注意:在一个类加载器中,类只能初始化一次),那就初始化直接的父类(不适用于接口)

3 ) 假如类中存在初始化语句(如static变量和static块),那就依次执行这些初始化语句。

类的加载

类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个这个类的Java.lang.Class对象,用来封装类在方法区类的对象。

类的加载的最终产品是位于堆区中的Class对象。 Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。

加载类的方式有以下几种:

1)从本地系统直接加载

2)通过网络下载.class文件

3)从zip,jar等归档文件中加载.class文件

4)从专有数据库中提取.class文件

5)将Java源文件动态编译为.class文件(服务器)

6)命令行启动应用时候由JVM初始化加载

7)通过Class.forName()方法动态加载

8)通过ClassLoader.loadClass()方法动态加载

加载器

JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述:

1)Bootstrap ClassLoader 负责加载$JAVA_HOME中 jre/lib/rt.jar 里所有的class或Xbootclassoath选项指定的jar包。由C++实现,不是ClassLoader子类。

2)Extension ClassLoader 负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar 或 -Djava.ext.dirs指定目录下的jar包。

3)App ClassLoader 负责加载classpath中指定的jar包及 Djava.class.path 所指定目录下的类和jar包。

4)Custom ClassLoader 通过java.lang.ClassLoader的子类自定义加载class,属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader。

加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载,就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。

结束生命周期

在如下几种情况下,Java虚拟机将结束生命周期

1、执行了System.exit()方法

2、程序正常执行结束

3、程序在执行过程中遇到了异常或错误而异常终止

4、由于操作系统出现错误而导致Java虚拟机进程终止

JAVA高级篇(三、JVM编译机制、类加载机制)的更多相关文章

  1. Java面试题:JVM中的类加载机制

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

  2. jvm虚拟机笔记<三> 类文件结构与类加载机制

    java虚拟机具有语言无关系,它只和“class文件“这种特定的二进制文件格式绑定. 不同语言的编译器将对应的程序编译成字节码文件(*.class),送给jvm执行. class文件本质上就是一张表, ...

  3. Java虚拟机笔记(一):类加载机制

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

  4. JAVA高级篇(二、JVM内存模型、内存管理之第二篇)

    本文转自https://zhuanlan.zhihu.com/p/25713880. JVM的基础概念 JVM的中文名称叫Java虚拟机,它是由软件技术模拟出计算机运行的一个虚拟的计算机. JVM也充 ...

  5. 《深入理解Java虚拟机》-----第7章 虚拟机类加载机制——Java高级开发必须懂的

    代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步. 7.1 概述 上一章我们了解了Class文件存储格式的具体细节,在Class文件中描述的各种信息,最终都需要 ...

  6. JAVA高级篇(一、JVM基本概念)

    一.什么是JVM VM的中文名称叫Java虚拟机,它是由软件技术模拟出计算机运行的一个虚拟的计算机. JVM也充当着一个翻译官的角色,我们编写出的Java程序,是不能够被操作系统所直接识别的,这时候J ...

  7. JAVA高级面试总结-JVM篇

    1.Sun HotSpot VM,是JDK和Open JDK中自带的虚拟机,也是目前使用范围最广的Java虚拟机. 2.JVM内存分布 程序计数器:是一块较小的内存空间,可以看作是当前线程所执行的字节 ...

  8. Java高级篇 JVM

    JVM是什么? JVM起了什么作用? JVM包含了什么? JVM中, 一个类 程序是怎么加载的? JVM中垃圾回收机制?

  9. 【JVM】JVM系列之类加载机制(四)

    一.前言 前面分析了class文件具体含义,接着需要将class文件加载到虚拟机中,这个过程是怎样的呢,下面,我们来仔细分析. 二.什么是类加载机制 把class文件加载到内存,并对数据进行校验.转换 ...

随机推荐

  1. kruscal重构树略解

    我们先看一道题:Luogu P4197 Peaks 这道题珂以用启发式合并+主席树来做 那么强制在线呢?(bzoj 3551 [ONTAK2010]Peaks加强版) 离线做法就不行了 我们就要用一个 ...

  2. [C++ Primer Plus] 第4章、复合类型(二)课后习题

    1.编写一个 c++ 程序,如下述输出示例所示的那样请求并显示信息 : What is your first name? Betty SueWhat is your last name? YeweWh ...

  3. 安装GDB-ImageWatch ,在QT中查看图像

    GDB_ImageWatch是在Linux下基于QT编写图像处理程序的调试程序. 由于并非像ImageWatch一样由官方提供,而是在github上以代码的方式进行提供,我们在使用的时候需要自己编译, ...

  4. CSS层叠样式表--使用

    一.颜色属性 二.字体属性三.背景属性四.文本属性五.边框属性六.列表属性七.display属性八.内外边距九.float属性十.定位十一.margin定位 一.颜色属性 (1)英文单词 <p ...

  5. NFS笔记

    NFS:Network File System (内核空间文件系统) ## 文件系统在内核空间,用户写数据-->系统调用 内核空间 硬件的操作   read()函数 write()函数 :过程调 ...

  6. redux-thunk的理解

    问题:1.redux-thunk要解决什么问题? 要解决异步请求问题,Action发出以后,Reducer立即算出State,这叫做同步:Action发出以后,过一段时间再执行 Reducer,这就叫 ...

  7. mysql数据库连接出问题,提示超时 java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.解决办法

    mysql数据库连接出问题,提示超时,后来发现问题在于连接mysql数据库的jar包跟数据库版本不对应导致的,更换jar包一致就解决了.

  8. 三层实现办公用品表CRUD(全过程)-ASP

    好久都没有写写技术博客了,自己最近几个月都要忙着搬家还有添置家当,所以一些博客就很少去写了,天道酬勤,有些吃饭的家伙还是不能有所懈怠,所以送上一个花了几小时给人事同事写的简单办公用品表的CRUD,希望 ...

  9. 运行Python出错,提示“丢失api-ms-win-crt-runtime-l1-1-0.dll”

    运行python时出错,提示“丢失api-ms-win-crt-runtime-l1-1-0.dll”, 上网搜了一下说是本地api-ms-win-crt-runtime-l1-1-0.dll 版本过 ...

  10. mysql数据库通过二进制 -【恢复数据记录】

    1.修改配置文件 vi /etc/my.cnf log-bin = binlog systemctl restart mysqld mysql -uroot -p123456 mysql> sh ...