classloader的工作模式

先说一下我的得出的结论 :

  1. 在java中 当你用一个类加载器 去加载一个类的时候 这个类里面所有的出现的过得类 都会通过这个类加载器加载在这个类后续    的操作中,只要是有由这个类衍生出的 那么涉及的类 都由这个类加载器进行加载 该类加载器为默认加载器。

2.  每个类加载器(应该说是类加载器的实例) 后面对应的其实是一堆class元信息  一个类加载器(应该是实例)的后面的东西,是一个大的圈圈,从这个类加载器进去的类 这个类的实例 活动的  范围 就在这个 加载器的范围中,别的类加载器不认识你,不会识识别你,即使是同一个类。

3. 类通过类的命名空间,与加载自己的类加载器建立联系。

 

下面结合代码说一下:

首先我自定义了一个类加载器

public class FatherLoader extends ClassLoader{

    public Class loadClass(String name) throws ClassNotFoundException {
        System.out.println("============FatherLoader=============loadClass:"+name);
        Class c = findLoadedClass(name);
        if (c == null) {
            if (name.startsWith("java"))
                return super.loadClass(name);
            String path = checkCouldLoad(name);
            if (path == null || "".equals(path))
                return null;
            else
                return realLoad(path);
        }
        return c;
    }
.....
}

然后定义了一下些基本的类

public class ShowInfo {
    public  void show(Entity en){
        System.out.println( " method in");
        Entity rnn=(Entity)en;
        System.out.println(rnn.name);
    }
}

public class Entity {
    public String name="zy";
}

然后建立一个测试类 用自定义的类加载器去加载

public class LoaderTest {
   static {
        try {
            
            Entity en=new Entity();     
            ShowInfo show = (ShowInfo) new FatherLoader().loadClass("com.laozhao.entity.show.ShowInfo").newInstance();
            show.show(en);
           /* 
           Method[] methods=shop.getClass().getDeclaredMethods();
            for(Method itm: methods){
                if(itm.getName().contains("show"))
                {
                    itm.invoke(en);
                }
            }*/
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

然后使用main方法去调用

public static void main(String[] args) throws Exception {
       new FatherLoader().loadClass("com.laozhao.loader.LoaderTest").newInstance();
    }

然后就报错了

============FatherLoader=============loadClass:com.laozhao.loader.LoaderTest
============FatherLoader=============loadClass:java.lang.Object
============FatherLoader=============loadClass:java.lang.Throwable
============FatherLoader=============loadClass:java.lang.Exception
============FatherLoader=============loadClass:com.laozhao.entity.Entity
============FatherLoader=============loadClass:java.lang.System
============FatherLoader=============loadClass:java.lang.StringBuilder
============FatherLoader=============loadClass:java.lang.Class
============FatherLoader=============loadClass:java.io.PrintStream
en:com.laozhao.loader.FatherLoader
============FatherLoader=============loadClass:com.laozhao.loader.FatherLoader
============FatherLoader=============loadClass:java.lang.ClassLoader
============FatherLoader=============loadClass:java.lang.CharSequence
============FatherLoader=============loadClass:java.io.InputStream
============FatherLoader=============loadClass:java.io.FileInputStream
============FatherLoader=============loadClass:com.laozhao.entity.show.ShowInfo
============FatherLoader=============loadClass:java.lang.String
============FatherLoader=============loadClass:java.net.URL
============FatherLoader=============loadClass:java.io.File
============FatherLoader=============loadClass:java.lang.Object
============FatherLoader=============loadClass:com.laozhao.entity.show.ShowInfo
java.lang.ClassCastException: com.laozhao.entity.show.ShowInfo cannot be cast to com.laozhao.entity.show.ShowInfo
	at com.laozhao.loader.LoaderTest.(LoaderTest.java:18)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at com.laozhao.Main.main(Main.java:20)

结合打印的日志 可以看到 在使用FatherLoader记载并初始化LoaderTest的时候 所有相关的类也都通过FatherLoader进行了记载,仔细看报错信息,你会发现非常有趣java.lang.ClassCastException: com.laozhao.entity.show.ShowInfo cannot be cast to com.laozhao.entity.show.ShowInfoShowInfo不能强转为ShowInfo,除了强转我还试了反射,报的错和这个差不多,原因也很简单,那是:

 ShowInfo show = (ShowInfo) new FatherLoader().loadClass("com.laozhao.entity.show.ShowInfo").newInstance();

在这行代码中 = 左边的类和右边的类尽管来自同一个class文件 是由不同的类加载器实例加载的 彼此是隔离的 不认识,所以无法强转,报的错也贼有意思。

换成下面这样就可以了:

ShowInfo show = (ShowInfo) LoaderTest.class.getClassLoader().loadClass("com.laozhao.entity.show.ShowInfo").newInstance();

这样就保证同一个类加载器实例了或者直接这样:

ShowInfo show=new ShowInfo();

使用new关键字 自动使用默认的类加载器 也就是加载LoaderTest的加载器

你可能感兴趣的:(java)