关于java classLoader的一些问题

原创
2016/06/18 18:06
阅读数 32

根据类加载机制自定义的一个类加载器,逻辑大致如下:

  1. 继承ClassLoader 
     
  2. 重写findClass
    @Override
    	protected Class<?> findClass(String name) throws ClassNotFoundException {
    		System.out.println("自定义查找 __find class :" + name);
    		byte[] classData = getClassData(name);//读取自定义的class文件
    		if (classData == null) {
    			throw new ClassNotFoundException();
    		} else {
    			System.out.println("自定义define __define class" + name);
    			return defineClass(name, classData, 0, classData.length);
    		}
    	}

     

  3. 使自定义类加载器支持非双亲委托机制加载class
    	@Override
    	public Class<?> loadClass(String name) throws ClassNotFoundException {
    		// || name.equals("deep.beans.A")
            //deep.beans.A 为自定义的一个接口,此处'name.equals("deep.beans.A")'是为了让接口使用不同的类加载器加载
    		if (name.startsWith("java") || name.equals("deep.beans.A")) {
    			return loadClass(name, false);
    		} else {
    			synchronized (getClassLoadingLock(name)) {
    				// First, check if the class has already been loaded
    				Class<?> c = findLoadedClass(name);
    				if (c == null) {
           //直接查找而不委托父类加载器
    					c = findClass(name);
    					resolveClass(c);
    				}
    				return c;
    			}
    		}
    	}
          //自定义加载方法
    	public Class<?> selfloadClass(String name, boolean isDefaultLoadOrder) throws ClassNotFoundException {
    		if (isDefaultLoadOrder) {
    			System.out.println("启用双亲委派机制 加载 class[" + name + "]");
    			return super.loadClass(name);
    		} else {
    			System.out.println("启用自定义类加载机制加载 class[" + name + "]");
    			return this.loadClass(name);
    		}
    	}

     

以下是我的一些测试,
接口:interface deep.beans.A ,类 :deep.beans.Person extends A,将A 和Person编译成class文件后放到 一个独立的目录下,与当前工作环境中的A 和Person 做对照试验

  1. 使接口A用系统类加载器加载,实现类Person用自定义类加载加载:
    	    Class clazz1 = cloc.selfloadClass("deep.beans.Person", false);//true :使用双亲委派机制,false只使用自定义的findClass方法
    	    System.out.println(Thread.currentThread().getContextClassLoader().getSystemClassLoader());
    		System.out.println(A.class + "  " + A.class.getClassLoader());
    		System.out.println(clazz1.getClassLoader());
    		System.out.println(clazz1.getInterfaces()[0] + "  " + clazz1.getInterfaces()[0].getClassLoader());
    	    A a = (A) clazz1.newInstance();
    		a.s("aaaaaaaaaaaaaaa");
    执行结果:
    sun.misc.Launcher$AppClassLoader@45ee12a7
    interface deep.beans.A  sun.misc.Launcher$AppClassLoader@45ee12a7
    deep.classloader.MyClassLoader@255316f2
    interface deep.beans.A  sun.misc.Launcher$AppClassLoader@45ee12a7
    aaaaaaaaaaaaaaa
    ---------------------------------
    可以看出接口与实现类使用的是不同的类加载器加载的.但是将与接口不同加载器加载的实现类赋值给接口的时候,却是没有问题的,这就让我突然觉得有点奇怪.



     


  2.  

  3.  

  4.  
  5.  

     



 

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部