类加载器[3]自定义类加载器[0]

在遵循父类委托机制的情况下,要实现自己的类加载器,只需要继承ClassLoader并重写他的findClass()方法。原理参见父类委托机制[0]”章节。

 

现将如下源代码编译成.class文件,把com\bjsxt\test\HelloLoader.class放到D:\temp目录下

 Java Code 


package com.bjsxt.test;

public class HelloLoader {
    
    
public static void sayLoader(){
        System.out.println(
"I am in app classPath");
    }
}

 

自定义一个类加载器,支持从指定目录读取.class文件并加载。

 JavaCode 


package com.bjsxt.test;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
 * 
自定义类加载器
 * 
支持从指定文件夹加载类
 * @author ShadowfaxGHH
 *
 */

public class CustomSystemClassLoader extends ClassLoader {

    
private String rootDir;

    
public CustomSystemClassLoader(String rootDir) {
        
this.rootDir = rootDir;
    }

    @Override
    
protected Class<?> findClass(String name) throws ClassNotFoundException {
        
// 从自定义目录读取文件,转化为一个字节数组
        byte[] classData = loadClassBytes(name);

        
if (classData == null) {
            
throw new ClassNotFoundException();
//这个地方抛出异常会导致//一直向下到自定义类加载器,尝试加载,如果还加载不上报ClassNotFoundException

        } else {
            Class c = defineClass(name, classData, 
0, classData.length);
            
return c;
        }

    }

    
private byte[] loadClassBytes(java.lang.String name) {

        
String path = rootDir + "/" + name.replace(".""/") + ".class";

        InputStream is = null;
        ByteArrayOutputStream baos = null;

        
try {
            is = 
new FileInputStream(path);
            baos = 
new ByteArrayOutputStream();

            
byte[] buffer = new byte[1024];
            
int ret = 0;
            
while ((ret = is.read(buffer)) != -1) {
                baos.write(buffer, 
0, ret);
            }

            
return baos.toByteArray();

        } 
catch (FileNotFoundException e) {
            e.printStackTrace();
        } 
catch (IOException e) {
            e.printStackTrace();
        } 
finally {
            
try {
                
if (is != null)
                    is.close();

                
if (baos != null)
                    baos.close();
            } 
catch (IOException e) {
                e.printStackTrace();
            }
        }

        
return null;
    }
}

 

使用如下代码进行测试,并且可以看到,自定义类加载器默认添加到父类委托机制的最底端

 JavaCode 


package com.bjsxt.test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 
测试自定义的FileSystemClassLoader
 * @author ShadowfaxGHH
 *
 */

public class Test {

    
public static void main(String[] args) {
        CustomClassLoader loader=
new CustomClassLoader("D:/temp");
        
        
try {
            Class<?> clazz = loader.loadClass(
"com.bjsxt.test.HelloLoader");
            ClassLoader classLoader = clazz.getClassLoader();
            System.out.println(classLoader);
            
            
//并且自定义类加载器默认添加到父类委托机制的最底端
            while(classLoader.getParent()!=null){
                System.out.println(classLoader.getParent());
                classLoader=classLoader.getParent();
            }
            
            
//反射调用方法
            Method declaredMethod = clazz.getDeclaredMethod("sayLoader", null);
            declaredMethod.invoke(null, null);
            
        } 
catch (ClassNotFoundException e) {
            e.printStackTrace();
        } 
catch (NoSuchMethodException e) {
            e.printStackTrace();
        } 
catch (SecurityException e) {
            e.printStackTrace();
            e.printStackTrace();
        } 
catch (IllegalArgumentException e) {
            e.printStackTrace();
        } 
catch (InvocationTargetException e) {
            e.printStackTrace();
        } 
catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

}

 


 

注意工程中不要再有HelloLoader.java文件,不然会被AppClassLoader加载上。

 

其实这里实现的功能在父类委托机制中已经实现了,这里只是讲解一下如何重写ClassLoader来实现自定义ClassLoader

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值