JVM类加载机制--双亲委派

本文详细阐述了JavaJVM的类加载机制中的双亲委派过程,包括`sun.misc.Launcher.AppClassLoader#loadClass`方法的工作原理,以及为何选择从当前类加载器开始并涉及双亲委派的原因,探讨了性能和命名空间的考虑因素。
摘要由CSDN通过智能技术生成

JVM类加载机制–双亲委派

1.sun.misc.Launcher.AppClassLoader#loadClass

最近重新看下java类加载器,大家都知道双亲委派模式,即先进入当前类加载器(默认是AppClassLoader)的sun.misc.Launcher.AppClassLoader#loadClass方法。核心逻辑:

SecurityManager.checkPackageAccess方法检查当前线程是否有权限访问指定的包。

sun.misc.URLClassPath#knownToNotExist方法标识是否已知指定的类或资源不存在。

​ -如果返回true,标识该类已知不存在。则进入当前类加载器的java.lang.ClassLoader#findLoadedClass0方法,查找类是否已经被加载到内存中,

​ -如果已经被加载进内存则Class对象不为空,执行java.lang.ClassLoader#resolveClass方法解析该类。即类加载阶段(加载、链接、初始化)中链接阶段的:验证、准备、解析中的解析。

​ -如果当前内存中找不到Class对象,则表示类不存在。抛出ClassNotFoundException。

​ -如果返回false,标识该类不是已知不存在,则进入父类的java.lang.ClassLoader#loadClass(java.lang.String, boolean)方法。不过注意当前还是在默认的AppClassLoader中,后续才是双亲委派的核心代码。

在这里插入图片描述

2.java.lang.ClassLoader#loadClass(java.lang.String, boolean)

synchronized (getClassLoadingLock(name))方法就是

在这里插入图片描述

  • 疑问: 为什么双亲委派模式要从当前类加载器开始执行,之前没加载过优先去让父加载器去加载。为什么不能先查缓存当前没有的话,直接由BootStrap类加载器先去加载,加载不到再找子加载器,直到最后加载不到抛出异常?
网上有个答案稍微能解释就是:这样自定义类加载器的时候,父类加载器会找不到自定义的子类加载器。

但是我觉得程序能解决这个问题。只要有个地方来注册子加载器,父类加载器就可以去这个缓存中获取到子类加载器。
GPT有个答案是:因为子类加载器能访问父类加载器已经加载好的类(存在于父类加载器的命名空间,这块是虚拟机底层的实现),但是父类加载器不能访问子类加载器的命名空间。

但是实际上难道不是已经加载的类都在缓存中吗,缓存还会按照不同的类加载器来区分吗?这个得去findLoadedClass方法的实现中去确定,目前没看到该方法需要传入classLoader对象。
我个人理解:
1.类似就是一个树的结构,子类加载器可能是多个(参考Tomcat的自定义类加载器)。父类是一子类是多。在父类里维护子类属性,那需要通过集合的结构来维护。在子类里维护父类的属性,只需要一个指针即可。这种实际上就是当初的设计方案定了这样,后续就这样去实现了。
2.可能和耗费的性能有关,直接使用BootStrap类加载器比通过子类加载器委派性能上更差,所以使用委派的模式。

实际上可能是和底层native方法的具体实现有关,如果命名空间中的缓存确实和类加载器本身有关,父类加载器访问不到子类加载器已经加载好的类,那确实就应该由最底层的类加载器开始加载,因为他能访问都已经加载好的所有的类。目前网上的内容基本上没有表述出来这块的,说的都是双亲委派就应该这么设计。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值