使用自定义类加载器加载class

 

 

 

操作流程都在代码注释中:

 

 

/**
 * 自定义文件系统类加载器 ---->使用自定义类加载器加载 某一目录下的字节码 
 * @author 
 * 将d:/myjava/com/zm/HelloWorld.class 通过自定义类加载器加载
 * 
 * 1 extends ClassLoader 重写findClass(String name)
 * 2 findClass(String name)内先去findLoadedClass(name)中找 没找到在去parent.loadClass(name)找,在没找到则用自己的代码
 *   写流获取目标文件的byte[]
 * 3 根据  c = defineClass(name, classData, 0,classData.length);得到Class对象并返回即可
 *
 */
public class FileSystemClassLoader extends ClassLoader {
	
	// d:/myjava/      
	private String rootDir;
	
	public FileSystemClassLoader(String rootDir){
		this.rootDir = rootDir;
	}
	
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		// 先去加载器里面看看已经加载到的类中是否有这个类
		Class<?> c = findLoadedClass(name); // loader.loadClass("com.zm.HelloWorld");
		
		//应该要先查询有没有加载过这个类。如果已经加载,则直接返回加载好的类。如果没有,则加载新的类。
		if(c!=null){
			return c;
		}else{
			ClassLoader parent = this.getParent();
			try {
				c = parent.loadClass(name);	   //委派给父类加载  调用JVM委托机制来加载,如果一层层上抛都没有加载到com.zm.HelloWorld的话 则走到46行 调用自己的类加载
			} catch (Exception e) {
//				e.printStackTrace();
			}
			
			if(c!=null){
				return c;
			}else{// 
				byte[] classData = getClassData(name);
				if(classData==null){
					throw new ClassNotFoundException();
				}else{
					// 将字节码处理成 Class实例返回
					c = defineClass(name, classData, 0,classData.length);
				}
			}
			
		}
		
		return c;
		
	}
	
	// 读取流 将读到的流处理成字节码数组返回
	private byte[] getClassData(String classname){   //com.zm.HelloWorld   d:/myjava/  com/zm/HelloWorld.class
		String path = rootDir +"/"+ classname.replace('.', '/')+".class";
		
//		IOUtils,可以使用它将流中的数据转成字节数组
		InputStream is = null;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try{
			is  = new FileInputStream(path);
			
			byte[] buffer = new byte[1024];
			int temp=0;
			while((temp=is.read(buffer))!=-1){
				baos.write(buffer, 0, temp);
			}
			
			return baos.toByteArray();
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			try {
				if(is!=null){
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if(baos!=null){
					baos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	
	
	
}




2 


public class Demo03 {
	public static void main(String[] args) throws Exception{
		FileSystemClassLoader loader = new FileSystemClassLoader("d:/myjava");
		FileSystemClassLoader loader2 = new FileSystemClassLoader("d:/myjava");
		
		Class<?> c = loader.loadClass("com.zm.HelloWorld");
		Class<?> c2 = loader.loadClass("com.zm.HelloWorldd");
		Class<?> c3 = loader2.loadClass("com.zm.HelloWorld");

		Class<?> c4 = loader2.loadClass("java.lang.String");
		Class<?> c5 = loader2.loadClass("com.zm.HelloWorld");
		
		
		System.out.println(c.hashCode());
		System.out.println(c2.hashCode());
		System.out.println(c3.hashCode());	//同一个类,被不同的加载器加载,JVM认为也是不相同的类
		System.out.println(c4.hashCode());
		System.out.println(c4.getClassLoader());	//引导类加载器
		System.out.println(c3.getClassLoader());	//自定义的类加载器
		System.out.println(c5.getClassLoader());	//系统默认的类加载器
		
	}
}

 

 

你可能感兴趣的:(Class)