类加载器(二)

在MyEclipse中编辑代码时,一旦保存,便会将源代码编译成class文件。

package com.interview.classLoader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
/**
 * 自定义类加载器,加密并加载class文件
 * @author dhh
 * 继承ClassLoader:
 * 使用方法 getSystemClassLoader() 返回的 ClassLoader 创建一个新的类加载器,将该加载器作为父类加载器。
 * 那么MyClassLoader2就为系统类加载器的一个子类,会继承loadClass实现委托机制(即抛给上级类加载器加载)
 */
public class MyClassLoader2 extends ClassLoader{
	//路径名
	public String destDir = null;
	//构造方法
	public MyClassLoader2(){}
	public MyClassLoader2(String destDir){
		this.destDir = destDir;
	}
	
	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws Exception{
		//可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类
		/**
		 * JDK API:
		 * loadClass使用指定的二进制名称来加载类。此方法的默认实现将按以下顺序搜索类: 
		 * 1、调用 findLoadedClass(String) 来检查是否已经加载类。
		 * 2、在父类加载器上调用 loadClass 方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。 
		 * 3、调用 findClass(String) 方法查找类。
		 * 因此写自定义类加载器要重写findClass(String)方法
		 * 
		 * 分析:
		 * 调用MyClassLoader2加载器,它会调用父类的loadClass,以此类推,BootStrap,ExtClassLoader调用findClass(String)都没有找到
		 * 轮到AppClassLoader,如果路径loadClass("com.interview.classLoader.enPackage"),可以找到类
		 * 如果将类替换成加密的class,可能会加载错误.
		 * 如果还是删除了com.interview.classLoader包中的enpackage.class,父类都找不到
		 * 就到了自定义的类加载器findLoad方法来加载,所以在这个方法中还要定义解密
		 * 才能得到正确的class
		 */
		Class clazz = new MyClassLoader2("myclass").loadClass("enPackage");
		//类enPackage在加密的时候是实现了父类Date的,不过这是为什么呢?
		//因为编译器无法确定加密后的enPackage,所以会报错
		//所以用enPackage继承的父类Date来创建,这样编译器能够识别
		Date myclazz = (Date)clazz.newInstance();
		System.out.println(myclazz);  //改写了toString()方法

	}
	
	@SuppressWarnings("deprecation")
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		InputStream input = null;
		ByteArrayOutputStream output = null;
		//相对项目的完整路径
		String className = destDir + "\\" + name +".class";
		try {
			input = new FileInputStream(className);
			output = new ByteArrayOutputStream();
			enCode(input,output);             //解密
			return defineClass(output.toByteArray(), 0, output.toByteArray().length);
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				input.close();
				output.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	
	/**
	 * 简单加密解密算法
	 * @param input
	 * @param output
	 */
	public void enCode(InputStream input,OutputStream output) throws Exception{
		int len = 0 ;
		while((len=input.read())!=-1){
			output.write(len^ 0xff);
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值