MyTest16 loader2 = new MyTest16(loader1,"loader2");
将loader1作为loader2的父类加载器,输出如下:
loader2会委托loader1去加载MyTest1,在第一次已经被加载过,所以第二次不再重复加载
保持MyTest1.class删除,增加loader3
public static void main(String[] args) throws Exception{
MyTest16 loader1 = new MyTest16("loader1");
// 在本地建立指定目录,然后删掉idea编译的MyTest1,可以发现findClass执行了
loader1.setPath("D:\\workspace\\");
// loader1.setPath("/d/workspace/jvm_lecture/target/classes/");
Class<?> clazz = loader1.loadClass("com.yshuoo.jvm.classloader.MyTest1");
System.out.println("class: " + clazz.hashCode());
Object object = clazz.newInstance();
System.out.println(object);
System.out.println("************");
MyTest16 loader2 = new MyTest16(loader1,"loader2");
loader2.setPath("D:\\workspace\\");
Class<?> clazz2 = loader2.loadClass("com.yshuoo.jvm.classloader.MyTest1");
System.out.println("class: " + clazz2.hashCode());
Object object2 = clazz2.newInstance();
System.out.println(object2);
System.out.println("************");
MyTest16 loader3 = new MyTest16("loader3");
loader3.setPath("D:\\workspace\\");
Class<?> clazz3 = loader3.loadClass("com.yshuoo.jvm.classloader.MyTest1");
System.out.println("class: " + clazz3.hashCode());
Object object3 = clazz3.newInstance();
System.out.println(object3);
}
可以看出,loader2和loader1在同一个命名空间,loader3和loader1,2不在同一个命名空间,所以loader3会自己加载
MyTest16 loader3 = new MyTest16(loader2,"loader3");
将loader2做为loader3的父类加载器
由于双亲委托模型这三个类加载器加载的都是同一个对象
类的卸载:
- 当MySample类被加载、连接和初始化后,它的生命周期就开始了。当代表MySample类的Class对象不再被引用,即不可触及时,Class对象就会结束生命周期,MySample类在方法区内的数据也会被卸载,从而结束MySample类的生命周期
- 一个类何时结束生命周期,取决于代表它的Class对象何时结束生命周期
由Java虚拟机自带的加载器所加载的类,在虚拟机的生命周期中,始终不会被卸载。
由用户自定义的类加载器所加载的类是可以被卸载的。
保持MyTest1删除,将loader1指向新的类加载器,在运行时加参数-XX:+TraceClassUnloading
public static void main(String[] args) throws Exception{
MyTest16 loader1 = new MyTest16("loader1");
// 在本地建立指定目录,然后删掉idea编译的MyTest1,可以发现findClass执行了
loader1.setPath("D:\\workspace\\");
// loader1.setPath("/d/workspace/jvm_lecture/target/classes/");
Class<?> clazz = loader1.loadClass("com.yshuoo.jvm.classloader.MyTest1");
System.out.println("class: " + clazz.hashCode());
Object object = clazz.newInstance();
System.out.println(object);
System.out.println("************");
// 为了验证被卸载,将所有引用都去掉
loader1 = null;
clazz = null;
object = null;
System.gc();
loader1 = new MyTest16("loader1");
// 在本地建立指定目录,然后删掉idea编译的MyTest1,可以发现findClass执行了
loader1.setPath("D:\\workspace\\");
// loader1.setPath("/d/workspace/jvm_lecture/target/classes/");
clazz = loader1.loadClass("com.yshuoo.jvm.classloader.MyTest1");
System.out.println("class: " + clazz.hashCode());
object = clazz.newInstance();
System.out.println(object);
}
可以看出确实卸载掉了第一个loader1