22-类加载器命名空间深度解析与实例分析

类加载器命名空间深度解析与实例分析

不同类加载器的命名空间关系:

  • 同一个命名空间内的类是相互可见的。
  • 子加载器的命名空间包含所有父类加载器的命名空间。因此由子加载器加载的类能看见父加载器加载的类。例如系统类加载器加载的类能看见根类加载器加载的类。
  • 由父加载器加载的类不能看见子加载器加载的类。
  • 如果两个加载器之间没有直接或者间接的父子关系,那么它们各自加载的类相互不可见。

实例一:

public class MyPerson {
    private MyPerson myPerson;
    public void setMyPerson(Object object) {
        this.myPerson = (MyPerson)object;
    }
}

public class MyTest20 {
    public static void main(String[] args) throws Exception {
        //MyTest16是一个自定义类加载器
        MyTest16 loader1 = new MyTest16("loader1");
        MyTest16 loader2 = new MyTest16("loader2");

        Class<?> clazz1 = loader1.loadClass("Jvm.MyPerson");
        Class<?> clazz2 = loader2.loadClass("Jvm.MyPerson");

        System.out.println(clazz1==clazz2);

        Object object1 = clazz1.newInstance();
        Object object2 = clazz2.newInstance();

        Method method = clazz1.getMethod("setMyPerson",Object.class);
        method.invoke(object1,object2);
    }
}
运行结果:
	true
  • 首先,打印该结果是由:System.out.println(clazz1==clazz2);是因为loader1、loader2去加载MyPerson的时候,都是由双亲委托机制,请求其父类加载器去加载,第一次loader1请求父类加载器(系统类加载器)完成加载;当第二次loader2加载的时候,请求父类加载器(系统类加载器)去加载,发现MyPerson已经被加载,就不再重新加载了,直接返回加载结果即可。

实例二:

//前提:删除out文件夹中的MyPerson.class,并将其复制到桌面上去。
public class MyTest21 {
    public static void main(String[] args) throws Exception {
        MyTest16 loader1 = new MyTest16("loader1");
        MyTest16 loader2 = new MyTest16("loader2");
        loader1.setPath("C:\\Users\\admin\\Desktop\\");
        loader2.setPath("C:\\Users\\admin\\Desktop\\");
        Class<?> clazz1 = loader1.loadClass("Jvm.MyPerson");
        Class<?> clazz2 = loader2.loadClass("Jvm.MyPerson");

        System.out.println(clazz1==clazz2);

        Object object1 = clazz1.newInstance();
        Object object2 = clazz2.newInstance();

        Method method = clazz1.getMethod("setMyPerson",Object.class);
        method.invoke(object1,object2);
    }
}
运行结果:
   findClass invoked:Jvm.MyPerson
   class loader name:loader1
   findClass invoked:Jvm.MyPerson
   class loader name:loader2
   -------------------
   false
   Exception in thread "main" java.lang.reflect.InvocationTargetException
   Caused by: java.lang.ClassCastException: Jvm.MyPerson cannot be cast to Jvm.MyPerson
  • 为false的原因:**如果两个加载器之间没有直接或者间接的父子关系,那么它们各自加载的类相互不可见。**所以loader1和loader2是两个不同类加载器(不同类加载器有着不同的命名空间,但是,在这两个不同的命名空间中有着相同的类MyPerson)。
发布了25 篇原创文章 · 获赞 0 · 访问量 1451

猜你喜欢

转载自blog.csdn.net/qq_40574305/article/details/104793474
今日推荐