JVM的类加载机制

要执行一个编写好的java文件,要经过编译和运行的过程。编译过程将java文件编译成.class二进制文件,运行时需要加载到JVM中,本篇文章记录jvm的类加载机制的学习笔记。

一、类加载的生命周期
在这里插入图片描述
由上图可以看出,Class类加载的整个生命周期中,包括5(加载、校验、准备、解析、初始化)个阶段,里面比较重要的三个阶段分别是:加载、连接、初始化
(1)加载:通过类的全限定名来获取定义此类的二进制字节流,将内部静态结构转化为方法区的数据结构,并在堆中生成一个java.lang.Class对象。jvm不会无条件装载Class类型,必须要求类或接口必须是主动引用(使用new关键字、反射等创建出类的实例,含有main()方法的类等才算主动引用),才能被装载。不满足主动引用的加载进入也不会完成初始化!
在这里插入图片描述

(2)连接:将已经读入内存的二进制数据合并到jvm运行时的环境中。
(3)初始化:jvm按照加载的文件的初始化语句在类文件中的先后顺序执行。

二、双亲委派机制
jvm的类加载是通过双亲委派机制完成的,说到这,就要先说类加载器。
类加载器:可以将classpath目录下的。class文件加载到内存中来进行一些处理,处理完毕的结果就是一些字节码。
jvm系统默认的三类加载器,顶层是BootStrap,这个加载器不是java类,不需要加载器加载,他可以加载ExtClassLoder和AppClassLoader加载器。
(1)BootStrap ClassLoader(启动类加载器):负责加载存放在JDK安装目录jre/lib下或者被-xbootclassloader参数指定的路径中的,并且能够被jvm识别的类库。所有的java.*开头的类均被BootStrap ClassLoader加载,该加载器无法直接java程序调用。
(2)Extension ClassLoder(扩展类加载器):负责加载JDK安装目录jre/lib/ext目录下或者由java.ext.dirs系统变量指定的路径中的所有类库,如javax . 开头的类,开发者可以直接使用扩展类加载器。
(3)Application ClassLoader(应用程序类的加载器):负责加载用户类路径下(Classpath)所指定的类,开发者可以直接使用该类加载器。如果应用程序没有自定义自己的类加载器,一般情况下默认使用这个。
当然自己也可以定义类加载器。
这些类加载器在实现方面的原理是一样的,不一样的是他们之间加载类的路径不一样。
在这里插入图片描述
双亲委托机制:如果一个类加载器收到了类加载数据的请求参数,他首先不会自己去尝试加载这个类,然是把这个请求委派给父加载器,每一层的类加载器都是如此,因此所有的加载请求最终都会传送到Bootstrap类加载器中,只有父类加载器反馈自己无法加载这个请求时,子加载器才会尝试自己去加载。
在这里插入图片描述
使用双亲委派机制的作用?
使用
三、实例说明
使用双亲委派机制的作用主要是保证JVM加载的类是唯一的,不存在重复。举个例子,你写了一个和JRE核心类同名的Object类,在加载的时候,Application ClassLader委托给Entsion ClassLader,在委托给BookStrap ClassLader ,BookStrap ClassLader发现已经加载过这个类,就不会在加载,他能保证java程序必要的类不存在重复、不能使用的情况。
也可以理解为,JVM的类加载器先加载自己本身的类,然后再加扩展的类,最后加载开发者写的类。

/*
* 测试jvm的类加载的过程
* */
public class ClassLoaderTest {

    public static void main(String[] args) {
        //1.获取当前类加载器
        ClassLoader c = ClassLoaderTest.class.getClassLoader();
        //2.遍历每一层的类加载器
        while(c!=null){//当前类加载器不为空
            System.out.println(c.getClass().getName());
            c = c.getParent();//赋值成父类加载器
        }
        System.out.println(c);
    }
}

运行结果为:
在这里插入图片描述
根据结果有两点要说明:
(1)顶层BootStrap是用C语言编写的类加载器,找不到确定的返回该加载器名字的方法所以才返回的null。
(2)父子类加载器之间并不是继承关系,只是他们的parent成员变量指向上层加载器。我们在编写的时候继承JDK提供的ClassLader抽象类,重写findClass(根据传入的类名在特定的路径下将这个类加载成Class对象 )、laderClass( 查找一下这个类是不是已经加载过了,默认使用双亲委托机制)即可。补充:Tomcat打破了双亲委托机制

总结
(1)java类从编译到运行的完整过程时什么样的?
一个java类经过编译生成class文件(字节码),然后通过jvm的类加载器加载到内存中进行处理,生成二进制码,最后运行。
(2)什么是类加载器?
类加载器就是将编译后生成的与类对应的class文件加载到内存中进行处理。jvm中默认的3中类加载器分别是顶层的BootStrap ClassLoader,子加载器Extension ClassLoader、Application ClassLoader三个,启动BootStrap是顶层的加载器,不是java类,不需要类加载器加载,它可以加载其他的类加载器。
(3)类装载流程时什么的?
首先将calss文件加载,然后连接(校验、准备、解析)操作,对于主动引用的类执行初始化,不是主动引用的类,不执行初始化。
(4)类加载中双亲委派机制是什么?
自己本身不加载,而是向上传给父加载器加载,一层一层知道顶层BootStrap ClassLoader,BootStrap ClassLoader就是加载类,如果它也找不到就会向下反馈,让子加载器加载。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值