两个加载器加载同一个类的实验

 

测试代码:

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调用批处理的例子。

 

你可能感兴趣的:(jvm,thread,exception,测试,null,Class)