黑马程序员-类加载器

------- android培训java培训期待与您交流 ----------

类加载器:

系统默认有3个类加载器 AppClassLoader >> ExtClassLoader >> BootStrap

  AppClassLoader:加载CLASSPATH指定的所有jar或目录

  ExtClassLoader:加载jre/lib/ext/*.jar,加载ext下所有的jar

  BootStrap:加载jre/lib/rt.jar ,加载lib下的rt.jarBootStrap不是java类,所以BootStrap的字节码为null,他是用C++写的一段二进制代码

Java虚拟机要加载一个类时:

  首先用当前线程的类加载器去加载线程中的第一个类。

  如果说这个类中还引用了其他类,那也是用加载这个类的加载器去加载。

  也可以用ClassLoader.loadClass();方法来指定一个类加载器去加载。

委托机制:

  类加载器在加载的时候有一个委托机制,也就是说当前加载器不会马上在自己的范围内找类加载,而是委托上级进行加载,一直委托到BootStrap,如果BootStraprt.jar中没找到就又一级一级的返回在其他加载器查找加载,如果返回到当前加载器也没有找到该类的话就抛出异常: ClassNotFoundException,即使当前加载器下还有加载器也不会向下查找了。

  委托机制还有个一个好处就是可以保证一个类只被加载一次,如果还要去加 载的话会先根据这个委托机制上下看一看这个类被加载过没有,如果加载过 了直接返回一份字节码就是了。

自定义类加载器加密class文件:

  创建一个类继承ClassLoader,创建一个加密的class文件的方法,重写finadClass方法(类加载器内部在加载类的时候是自动调用loadClass方法,而loadClass方法内部会自动的调用上级类加载器加载,以此类推,如果最后返回回来上级类加载器都没找到,则又loadClass()又调用本类的fiandClass方法,所有只重写fiandClass就行了)

 

public class ClassLoaderAttachment extends Date {
	public String toString(){
		return "hello,itcast heima";
	}
}
public class MyClassLoader extends ClassLoader {
	public static void main(String[] args) throws Exception {
		
		//接收传入的参数 ,一个为原class文件的地址,另一个为加密后文件的地址
		String srcPath = args[0];
		String destPath = args[1] + "\\" + srcPath.substring(srcPath.lastIndexOf("\\"));
		//读取文件
		FileInputStream fis = new FileInputStream(srcPath);
		//写入
		FileOutputStream fos = new FileOutputStream(destPath);
		//调用加密方法,对class文件进行加密
		cypher(fis,fos);
		fis.close();
		fos.close();
	}
	
	//加密
	public static void cypher(InputStream is, OutputStream os) throws Exception{
//		System.out.println("jiami");
		int b = -1;
		while((b = is.read()) != -1){
			os.write(b ^ 0xff);
		}
	}
	private String classDir;
	MyClassLoader(){}
	MyClassLoader(String classDir){
		//接收地址
		this.classDir = classDir;
	}
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		//拼接class文件地址
		name = classDir + "\\" + name + ".class";
		try {
			FileInputStream fis = new FileInputStream(name);
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			//对class文件进行解密
			cypher(fis,bos);
			fis.close();
			//获得字节数组
			byte[] buf = bos.toByteArray();
			bos.close();
			//把字节数组传入defineClass()方法 返回一个Class文件
			return defineClass(buf, 0, buf.length);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return super.findClass(name);
	}
}

public class ClassLoaderTest {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		//使用自定义加载器加载文件
//		Class clazz = new MyClassLoader("bin\\test\\enhance\\classloader").loadClass("ClassLoaderAttachment");
		Class clazz = new MyClassLoader("itcastlib").loadClass("ClassLoaderAttachment");
		//这里不能用ClassLoaderAttachment类接收,因为现在classPath里的class文件是被加了密的。
		Date date = (Date)clazz.newInstance();
		System.out.println(date.getClass().getClassLoader());
		System.out.println(date);
	}
}

问题:

rt.jar中有java.lang.System类,我可不可以自己再写一个java.lang.System来用?

答:rt.jar本来有System类的,而加载的时候又有委托机制,也就是说会最先找最上级,按照普通的方式的话自己写的System类是没有机会被加载到的,但是我们可以撇开委托机制,用特殊方法写一个类加载器去加载


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值