类加载器

创建bootstrapClassLoader,创建启动器Launcher。
父子加载器的类关系不是继承关系,子加载器通过parent变量引用父加载器。

为什么类加载的顺序不是从引导类加载器先加载,而是从应用类加载器加载?

因为只有AppClassLoader会检查类是否已被加载过。因为项目中大部分代码都是我们自己写的,都将被应用类加载器加载。参考加载顺序:一个没有被加载过的类,首先会让AppClassLoader加载(loadClass),查找该类是否已经被加载过了(findLoadedClass),没有加载过,向上委托父类加载器加载(parent.loadClass),父类加载器加载不了的,由子类加载器去对应路径(Bootstrap ClassLoader-》rt.jar,ExtClassLoader-》ext.jar,AppClassLoader-》classpath,一般是src/main/java下的文件)寻找对应包路径下的类文件(findClass),然后进行类加载过程(defineClass)。第一次会比较慢,但是被加载过一次后,直接就再第一步返回该类了,不会再走后续流程。如果先从父类加载器到子类加载器,那么大部分类都要经过父类加载器到子类加载器的流程。

一个tomcat下存在多个应用,A应用和B应用依赖的spring版本不同,怎么办?

如果不打破双亲委派机制,那么先加载的应用的spring版本,将会被Application ClassLoader加载,后加载的应用在AppClassLoader加载时会发现已经加载过,就不会重新进行加载,导致加载的类版本不对。
打破双亲委派机制:自定义classLoader,重写loadClass方法。比如Tomact类加载
tips:即使自定义类加载器,重写loadclass去加载自己定义的例如java.lang.String类也是不被允许的,报错java.lang.SecurityException: Prohibited package name: java.lang参考沙箱安全机制。

 

 

posted on 2023-03-19 20:43  zhengbiyu  阅读(18)  评论(0编辑  收藏  举报