关于 ClassLoader 的一些疑问
众所周知
jvm 里 class 的唯一标识是 classloader+包+类
现在我自定义了一个 classloader
public class MyClassLoader extends ClassLoader
从外部加载指定类进入 jvm
MyClassLoader mcl = new MyClassLoader(); Class<?> clazz = Class.forName("com.yuhan.demo.controller.People", true, mcl); obj = clazz.newInstance(); System.out.println(obj.getClass().getClassLoader());//打印出我们的自定义类加载器
这种加载方法应该是使用了双亲委托机制如果 AppClassLoader 已经加载过 People 了则不会重新加载
控制台输出
[email protected]
如果我们将 People.class 从 classpath 中删除放到其他地方,避免 AppClassLoader 直接加载
则输出
[email protected]
但是如果我们直接这样调用
mcl = new MyClassLoader(); aClass = mcl.findClass("com.yuhan.demo.controller.People"); obj =aClass.newInstance(); System.out.println(obj.getClass().getClassLoader());//打印出我们的自定义类加载器
则不管 AppClassLoader 是否加载过都会由 MyClassLoader 来加载(相当于绕过了双亲?)
现在我有个疑问就是我用 findClass 方法加载了一个 jvm 中已经存在的 class(包名类名都相同),相当于 jvm 中就有两个相同的 class 了(jvm 中是允许这样存在的因为 classloader 不同) 但是 java 中使用类的时候只指定了包名和类名并没有指定 classloader 那么 java 是如何保证我 new People 的时候是是用的 AppClassLoader 的 People 而不是 MyClassLoader 的 People 呢
我的猜测是我们直接使用类的时候 java 加上了默认的 classloader 从而过滤调了我们自己加载的类,而我们自己加载的类则只能通过反射来调用