测试代码:
Class cl = Class.forName("com.tang.test1.A");//使用AppClassLoader加载类
System.out.println(cl.getClassLoader());
Runtime.getRuntime().exec("cmd.exe /c c:/del.bat ");//删除当前路径下的.class文件
UserClassLoader loader = new UserClassLoader("D://dev//mycls");//使用自定义加载器加载类
Class c = loader.loadClass("com.tang.test1.A",true);
UserClassLoader中的关键代码:
result = findLoadedClass(className);
if (result != null) {
return result;
}
if(!className.equals("com.tang.test1.A")){//加载A类不去AppClassLoader
try {
result = super.findSystemClass(className);
if (result != null) {
return result;
}
} catch (ClassNotFoundException e) {
}
if (className.startsWith("java.")) {
throw new ClassNotFoundException();
}
}
输出:
sun.misc.Launcher$AppClassLoader@19821f
com.tang.test1.UserClassLoader@530daa
结论,UserClassloader中的findLoadedClass方法判断的是当前加载器是否已经加载了该类。就算AppClassLoader已经加载了A类,这个方法是不会返回的。
另外,如果把UserClassloader 中findLoadedClass这段代码注释掉,在测试代码后面再用自定义加载器调一次loader.loadClass("com.tang.test1.A",true);,因为自定义加载器不会再去找已经加载过的类,就会出现
Exception in thread "main" java.lang.LinkageError: loader ,jvm以此来控制同一个加载器不能两次加载同一个类,以此来控制不重复发明轮子,或者说,避免重复轮子带来的问题。
ps:测试代码中还有java调用批处理的例子。