JVM类加载器

JVM类加载器

在这里插入图片描述

类(class)加载过程

**1、Loading: **将class文件转载到内存中

**2、Linking : **

(1)Verification:校验,检测转载进来的class文件是否符合相关标准(比如校验开头的ca fa ba be).

(2)Preparation:(重要步骤),将类中的静态变量赋默认值(不是赋初值,比如类中写了一个 static int id = 8;这里会将id 赋值为 0 ;).

(3)Resolution:该class文件中所使用到的符号引用转化成直接的内存地址,即可以直接访问到。

**3、Initializing: **静态变量的赋值(赋初始值)以及调用静态代码块;

class文件被load到内存中之后,会产生两部分的内容,第一部分就是class文件被完整加载到内存里,另外一部分会创建一个class类的对象用来指向这段内存中的class文件,其他的class(类对象)需要使用的时候就通过这个class类对象来调用相应的功能。(class对象创建之后存放在 metespace 中<平常自己创建的对象都是放在堆中>)。


不同的类加载器

(1)Bootstrap------------>加载lib/rt.jar,charset.jar等核心类,Bootstrap是通过C++实现的。

//通过getClassLoader()可以去找到类加载器是什么,当输出为空时(null),说明是 Bootstrap加载的核心类 
//这里的String类就是一个核心类
System.out.println(String.class.getClassLoader());//输出为 null

(2)Extension------------>加载扩展jar包jre/lib/ext/*.jar或由-Djava.ext.dirs指定

在这里插入图片描述

(3)App--------------->加载classpath指定内容

(4)CustomClassLoader-------------------->自定义ClassLoader

public class Test {
    public static void main(String[] args) {
        
        System.out.println(String.class.getClassLoader());
        //null   (Bootstrap)
        
        System.out.println(sun.net.spi.nameservice.dns.
                           DNSNameService.class.getClassLoader()); 					         //sun.misc.Launcher$ExtClassLoader@7ea987ac  (Extension)
                             ^  
                                 
        System.out.println(Lombok.class.getClassLoader()); 									//sun.misc.Launcher$AppClassLoader@18b4aac2  (App)
                             ^
                                 
        System.out.println(Test.class.getClassLoader()); //当前的这个Test类					//sun.misc.Launcher$AppClassLoader@18b4aac2  (App)
                             ^
    }
}

BootStrap类加载 加载 其他的类加载器

除了Bootstrap类加载器,另外三个加载器往深处溯源,其实也会溯源到Bootstrap类加载器,因为类加载器本身也是类,类加载器是通过Bootstrap加载出来的

public class Test {
    public static void main(String[] args) {
        
        /*ExtClassLoader加载器的加载器是Bootstrap*/
/*1.*/  System.out.println(sun.net.spi.nameservice.dns
        				   		.DNSNameService.class.getClassLoader()); 	           		 //sun.misc.Launcher$ExtClassLoader@7ea987ac
        				   
/*2.*/  System.out.println(sun.net.spi.nameservice.dns
       					  		.DNSNameService.class.getClassLoader()
       					  			.getClass().getClassLoader());//null

		/*AppClassLoader加载器的加载器是Bootstrap*/
/*1.*/  System.out.println(Test.class.getClassLoader()); 							 		 //sun.misc.Launcher$AppClassLoader@18b4aac2
        
/*2.*/  System.out.println(Test.class.getClassLoader()
        						.getClass().getClassLoader());//null
        
    }
}

双亲委派机制(important):

双亲委派机制是jvm内部固定了的,无法进行修改,任何类class的加载都必须经过双亲委派进制。

双亲委派中 ‘’双亲 (父加载器)‘’ 不是指的类加载器的加载器(BootStrap),而是某个类加载器的上一级(如CustomClassLoader 的 父加载器是 Add )。

每一个加载器中有自己对应的一段存储空间(可能是list也可以是数组或者其他的)用来存储该加载器已经将哪一些类加载进去了;在加载某个(类)class文件之前,需要先通过自底向上检查该类是否已经加载进去了。

某个类的加载可能先找到了CustomClassLoader加载器,CustomClassLoader就会在自己的存储空间内查找是否有该类(class),如果发现有就直接返回不执行加载过程。如果存储空间没有找到,就向上申请查看App加载器中是否存在。

App加载器也去查找自己的存储空间看是否加载了这个类,如果发现有就直接返回不执行加载过程。如果存储空间没有找到,就向上申请查看Extension加载器中是否存在。

同理Extension加载器之后就是BootStrap加载器。

BootStrap加载器中也没有找到,那就说明这个类(class)的确是没有加载过的,这时就要加载这个类(class),首先BootStrap加载器判断这个类是否属于自己的加载范畴,如果是就由BootStrap加载,如果不是就向下给Extension加载器。

Extension加载器也判断这个类是否属于自己的加载范畴,如果是就加载,如果不是就向下给Add加载器。

Add加载器也同理进行判断,不是则向下给CustomClassLoader加载器。

CustomClassLoader也会进行判断加载,如果加载成功即返回,如果未加载成功就报class未找到异常(ClassNotFoundException)

在这里插入图片描述
在这里插入图片描述

双亲委派机制的作用?(为什么要这么繁琐的进行判断)

最重要的原因是保证class的安全,提高jvm的安全性:如果用户自定义一个类,类名与核心类库一样,假设为java.lang.String,但是用户自定义了他的加载器(CustomClassLoader加载器),不进行class类判断直接加载,那么该自定义的String类会覆盖掉核心类库的String类,开发者恶意在自定义String中加入了一些代码,执行某些程序,就有可能会导致用户很大的损失。而双亲委派机制就可以限制开发者指定String类的加载,提高了安全性。

行class类判断直接加载,那么该自定义的String类会覆盖掉核心类库的String类,开发者恶意在自定义String中加入了一些代码,执行某些程序,就有可能会导致用户很大的损失。而双亲委派机制就可以限制开发者指定String类的加载,提高了安全性。`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莽晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值