package dragon.classloader;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
DragonClassLoader classLoader1 = null, classLoader2 = null;
String url = System.getProperty("user.dir");
System.out.println(url);
classLoader1 = new DragonClassLoader(url);
classLoader2 = new DragonClassLoader(url);
Class<?> clazz1 = classLoader1.loadClass("dragon.classloader.Cat");
Class<?> clazz2 = classLoader2.loadClass("dragon.classloader.Cat");
System.out.println("clazz1: " + clazz1);
System.out.println("clazz2: " + clazz2);
System.out.println("clazz1 == clazz2: " + (clazz1 == clazz2));
}
}
说明:
这里的结果还是true,说明我这个实验是失败的。但是为什么呢?我们把目光向前移动,看到双亲委派模型的那幅图片,可以看出自定义的类加载器的关系是平行的,但是我这里只是一个自定义类加载器,所以我应该再去自定义一个类加载器来加载,这样它们才会为false吗?也不是,因为我当前加载得这个类它是在classpath下面的,而classpath下面的类是由系统类加载器,即 Application Class Loader 来加载的。所以,我还是在双亲委派模型的机制下,加载了我自己写的类,也就是没有破坏双亲委派模型。
下面让我们来证明一下,上面的解释是正确的吧,证明的方式很简单,只是两句打印语句而已!
对上面的代码修改如下 :
public static void main(String[] args) throws ClassNotFoundException {
DragonClassLoader classLoader1 = null, classLoader2 = null;
//这里这个url路径其实是不对的,当时代码没有问题,你继续往下看就会懂的。
//我也就不改了,作为一个错误示例给大家看看。
String url = System.getProperty("user.dir");
System.out.println(url);
classLoader1 = new DragonClassLoader(url);
classLoader2 = new DragonClassLoader(url);
Class<?> clazz1 = classLoader1.loadClass("dragon.classloader.Cat");
Class<?> clazz2 = classLoader2.loadClass("dragon.classloader.Cat");
System.out.println("clazz1: " + clazz1);
System.out.println("clazz2: " + clazz2);
System.out.println("clazz1 == clazz2: " + (clazz1 == clazz2));
System.out.println(clazz1.getClassLoader());
System.out.println(clazz2.getClassLoader());
}
如上,可以看出,即使是自定义的类加载器加载的也是使用了双亲委派模型的。但是按照上面那幅图来看,它应该是使用 DragonClassLoader 来加载呀?这是为什么呢?其实上面也说了,是和classpath有关。
原因详细:
类加载器的双亲委派模型中,每个类加载器是有一个加载范围的。
启动类加载器加载的是:
存放在<JAVA_HOME>\lib 目录中的,或者被 -Xbootclasspath 参数所指定的路径中的,并且是虚拟机识别的。(仅按照文件名识别,如 rt.jar,名字不符合的类库即使放在 lib 目录中也不会被加载)
扩展类加载器加载的是:
<JAVA_HOME>\lib\ext 目录中的,或者是被 java.ext.dirs 系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。
应用类加载器加载的是:
用户类路径(ClassPath)上所指定的类库。
那么怎么知道用户类路径是什么呢?
通过如下代码可快速知道:System.out.println(System.getProperty("java.class.path"));
结果为:
D:\JavaProject\SourceAnalysis\bin;C:\Program Files\Java\jdk1.8.0_241\bin
如下图所示,可以看到我的 Cat.class 字节码文件。
可以将代码修改为以下形式,其中使用f.readlines()方法读取文件中的所有行,并通过for循环逐行输出:
with open('file.txt', 'r') as f:
for line in f.readlines():
print(line)