专栏首页一枝花算不算浪漫的专栏JVM 学习笔记一 :JVM类加载机制

JVM 学习笔记一 :JVM类加载机制

前言:

最近在看JVM相关资料,这里记录下学习笔记,希望自己能坚持学完,打牢基础。

一、类加载过程

1,类从被加载到JVM中开始,到卸载为止,整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。

2,其中类加载过程包括加载、验证、准备、解析和初始化五个阶段。

二、Java类运行过程

我们编写完的程序都是以java结尾的文件,编译写完的代码都会生成一些后缀为class的字节码文件。

当执行java -jar命令后(以springboot为例),此时会启动一个JVM进程,然后通过类加载机制来将所需要的类加载到JVM中进行运行。

这样一个编译好的系统就可以运行起来了。

三、类加载机制

我们都知道类的加载是一个很繁琐的过程,基本流程如下:

加载-》验证-》准备-》解析-》初始化-》使用-》卸载

1、加载

到底什么时候该去加载一个类呢?答案就是在我们使用一个类的时候,以main() 函数为入口,当JVM启动的时候,它会将含有main()函数入口的代码加载然后开始执行。

首先是代码中含有main()函数,然后开始执行main()函数中的代码,接着遇到ReplicaMananger类,此时就会将对应的.class字节码文件加载到内存中。

2、验证|准备|解析

(1)验证阶段

简单来说,这一步就是根据Java虚拟机规范,来校验你加载进来的”.class”文件中的内容,是否符合指定的规范。

所以把”.class”加载到内存里之后,必须先验证一下,校验他必须完全符合JVM规范,后续才能交给JVM来运行。

(2)准备阶段

例如下面的一个”ReplicaMananger”类:

public class ReplicaMananger {
    Public static int flushInterval;
}

假如有上面的一个类,它的class文件内容刚被加载到内存之后,会进行验证,确认这个字节码文件的内容是规范的,接着进行准备工作。

准备工作其实就是为”ReplicaMananger”类分配一定的内存空间,然后给它里面的变量分配内存空间,来一个默认的初始值。

比如上面的示例中,就会给”flushInterval"这个变量分配内存空间,给一个”0”这个初始值。

(3)解析阶段

解析阶段,实际上就是把符号应用替换为直接引用的过程。

在程序编译时,java类并不知道所引用的类的实际地址,因此只能引用符号引用来替代。例如,在Class文件中它以class_info、fieldref_info、methodref_info等类型的常量出现。 

比如org.simple.People类引用了org.simple.Language类,在编译时,People类并不知道Language类的地址,因此只能使用org.simple.Language(假设是这个,当然实际是由类似于CONSTANT_Class_info的常量来表示的)来标识Language类的地址。直接引用可以是直接指向目标的指针、相对偏移量、一个能间接定位到目标的句柄。

3、核心阶段:初始化

上面说过,在准备阶段,就会给”ReplicaMananger”类给分配好内存空间,另外他的一个默认的初始值为”0”,那么在接下来,在初始化阶段,就会正式执行我们的类初始化代码了。

如上所示,flushInterval这个变量是由Configuration.getInt("replica.flush.interval")这段代码来获取一个值,并且赋值给他的。另外还比如在static静态代码块,也会在这个阶段来执行。

4、总结

一般来说,在new Class() 来初始化类对象时,会触发类的加载到初始化的全过程,把这个类准备好,然后是实例化一个对象出来。

或者是包含main()方法的主类,必须是立马初始化的。

此外,还有一个非常重要的规则,就是如果初始化一个类的时候,发现他的父类还没有初始化,那么必须先初始化他的父类。

四、双亲委托原则

Java中的类加载器

1,启动器加载器:Bootstrap ClassLoader

一旦JVM启动,那么首先就会依托启动类加载器,去加载Java安装目录下的”lib”目录下的核心类库。

2,扩展类加载器: Extension ClassLoader

这个类加载器也是类似的,就是Java安装目录下,有一个”lib\ext”目录,这里有一些类,就是需要使用这个类加载器来加载的。

3,应用程序内加载器:Application ClassLoader

这类加载器就是负责加载ClassPath环境变量中所指定路径中的类,可以理解为加载我们写好的Java代码。这个类加载器就负责加载我们写好的类到内存中。

4,自定义类加载器

除了上面几种,我们还可以自定义类加载器,根据自己的需求加载需要的类。

5,双亲委托机制

JVM类加载器有亲子层级结构的,如下图:

基于这个亲子层级结构,就有一个双亲委派的机制,也就是当我们加载一个类的时候,先找父亲去加载,不行的话再由儿子来加载。这样的话 可以避免多层级的加载器结构重复加载某些类。

6,双亲委派模式的优点:

采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。

其次是考虑到安全因素,java核心api中定义类型不会被随意替换,假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。 

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [Java类加载器]Java中classLoader浅析.

    一枝花算不算浪漫
  • 【一起学源码-微服务】Ribbon 源码二:通过Debug找出Ribbon初始化流程及ILoadBalancer原理分析

    上一讲讲了Ribbon的基础知识,通过一个简单的demo看了下Ribbon的负载均衡,我们在RestTemplate上加了@LoadBalanced注解后,就能...

    一枝花算不算浪漫
  • [读书笔记]C#学习笔记三: C#类型详解..

    一枝花算不算浪漫
  • Tomcat 类加载器打破双亲委派模型

    1. 什么是类加载机制? 2. 什么是双亲委任模型? 3. 如何破坏双亲委任模型? 4. Tomcat 的类加载器是怎么设计的?

    爱撸猫的杰
  • JVM真香系列:轻松理解class文件到虚拟机(下)

    上面我们自定义一个String出了问题,问题在于JVM不知道我们想用哪个类,于是JVM就定义了个规范。

    田维常
  • 今天来聊Java ClassLoader

    类加载机制作为一个高频的面试题经常会在面试中被问到,前几天一个电话面试就问到,之前有了解过,但是没有梳理成自己的体系,所以说的有点凌乱,今天花点时间整理一下,分...

    纯洁的微笑
  • Java类加载机制

    答:当某个类加载器在接到加载类的请求时,会将加载任务委托给父类加载器,依次递归,父类加载器可以完成类加载任务,就成功返回;不能加载则子类加载器自己完成加载。有3...

    宇宙之一粟
  • Java 类加载机制及双亲委派模型

    即 加载 → \rightar...

    Steve Wang
  • 浅谈Java类加载器

    注意最后的null值应该是启动类加载器、单因为是C++语言编写的,所以无法获取到相关的信息

    Java学习录
  • JVM学习第三天(JVM的执行子系统)之类加载机制补充

    对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。这句话可以表达得更通俗一些...

    彼岸舞

扫码关注云+社区

领取腾讯云代金券