JVM(二)详解Class加载过程

[](

)2. 双亲委派

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200512160140857.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM

【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】

浏览器打开:qq.cn.hn/FTf 免费领取

2MjY4MDI1,size_16,color_FFFFFF,t_70)

加载时目标的class先看自定义classloader是否加载了,如果没加载委托上一级app加载器去看看加载了没,如果没加载就继续向上挨个找,如果最顶层bootstrap也没加载,则从最顶层依次向下委派让子加载器加载这个class,如果这个class不是属于这个子加载器可以加载的范围则继续向下委派,如果最后都不能加载则抛出classNotFoundException,以上过程只要有一个找到了就直接返回结果。

面试:为什么类加载器要用双亲委派?

答:主要安全,比如说有一个java.lang.string的包要加载,如果没有双亲委派,直接拿来最低级classloader直接加载到内存使用,就把sun公司的String覆盖了,如果客户在输密码的时候我在包里做了个记录密码的手脚就很危险,而双亲委派发现string要加载那一直找到bootstrap发现sun有了,那直接把sun的string返回;次要是之前已经加载过了就不用了再加载了。

在这里插入图片描述

类加载器中有个parent成员变量是classloader指向谁谁就是parent。

在这里插入图片描述

上图中$后代表前面这个类的内部类

[](

)3. 类加载器的范围

在这里插入图片描述

[](

)4. 自定义类加载器

在这里插入图片描述

Class clazz = T005_LoadClassByHand.class.getClassLoader().loadClass(“com.testJvm.jvm.c2_classloader.T002_ClassLoaderLevel”);

上为加载类,T005…为当前类名,最后参数是你想要加载的包名.类名。

T005_LoadClassByHand.class.getClassLoader().getResourceAsStream("");

上为利用类加载器可以加载静态资源。

classLoader源码:

loadClass()方法(内部已经写好了双亲委派的过程)

在这里插入图片描述

上图类似递归调用,找不到就父类调用loadClass(本方法),最后也找不到就会调用findClass(),findClass方法源码中只有抛异常的一句话,是受保护的关键字修饰,具体的实现是子类中才能看到,这是钩子函数、模板函数的设计模式(写到一半,提供模板,具体子类实现)(面试设计模式可以引到classloader的源码中,加分项)!【有趣的题外话:历史上有两次jdk自己破坏了双亲委派,可以百度搜一下具体发生了啥】

自定义类加载器:

public class T006_MSBClassLoader extends ClassLoader {

@Override

protected Class<?> findClass(String name) throws ClassNotFoundException {

File f = new File(“c:/test/”, name.replace(".", “/”).concat(".class"));

try {

FileInputStream fis = new FileInputStream(f);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

int b = 0;

while ((b=fis.read()) !=0) {

baos.write(b);

}

byte[] bytes = baos.toByteArray();

baos.close();

fis.close();//可以写的更加严谨

return defineClass(name, bytes, 0, bytes.length);//将流转换为class对象,name:类名;bytes:内存中哪部分字节数组;off:字节数组起始位置;bytes.length:字节数组结束位置。

} catch (Exception e) {

e.printStackTrace();

}

return super.findClass(name); //throws ClassNotFoundException

}

public static void main(String[] args) throws Exception {

ClassLoader l = new T006_MSBClassLoader();

Class clazz = l.loadClass(“com.testJvm.jvm.Hello”);

Class clazz1 = l.loadClass(“com.testJvm.jvm.Hello”);

System.out.println(clazz == clazz1);

Hello h = (Hello)clazz.newInstance();//反射new一个对象

h.m();

System.out.println(l.getClass().getClassLoader());

System.out.println(l.getParent());

System.out.println(getSystemClassLoader());

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值