黑马程序员——类加载器

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

 

类加载器

类是由类加载器将类以二进制形式加载到虚拟机中的

 

类加载器本身也是一个Java

BootTramp, ExtClassLoader, AppClassLoader

它们之间是树形的关系, BootTramp是在虚拟机中的类加载器,主要加载rt.jar里面的类,它是所有加载器最上面的一级, ExtClassLoader是加载ext文件夹下的jar,是一些扩展的类, 是加载器中的第二级, AppClassLoader加载的是classpath下的类,是第三级

 

代码示例

package cn.itcast.classloader;

 

publicclass LoaderTest1 {

    publicstaticvoid main(String[] args) {

       //测试当前类的类加载器和它的父类以及父类的父类等的加载器,如果加载器是BootStrap,那么它是null

       ClassLoader loader = LoaderTest1.class.getClassLoader();

       //循环得到每一层loader

       while (loader !=null) {

           System.out.println(loader.getClass().getName());

           loader = loader.getParent();

       }

       //loadernull,表示它是BootStrap,因为它是虚拟机里面的,所以值为null

       System.out.println(loader);

    }

}

 

类加载器的委托机制

但类A中调用了类B,那么会用类A的类加载器来加载类B,类加载器在加载类B,首先是将加载器委托给最上级的加载器去加载, 如果没有,就用下一级来加载, 当类加载器是当前A的加载器时,就不会再往下找了是从类加载器树形的顶端开始加载的, 直到当前加载器为止,这叫做类的委托机制

 

可以自定义类加载器, 只要继承ClassLoader抽象类,可以指定类的类加载器, 不过要重写ClassLoader中的findClass(String className)方法

 

代码示例

 

使用自定义类加载器加载加过密的.class文件

 

//要被加密的类Test1
package cn.itcast.classloader;

public class Test1 {
	//构造方法中打印一句话
	public Test1() {
		System.out.println("hello itcast");
	}
}

//自定义的类加载器, 其中包含了将文件加密解密的方法, 并对Test1进行了加密

package cn.itcast.classloader;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class MyClassLoader extends ClassLoader {
	
	private String classDir;


	public MyClassLoader() {
		
	}
	
	//构造方法接收一个字符串
	public MyClassLoader(String classDir) {
		this.classDir = classDir;
	}
	
	
	//给文件加密, 解密方法
	public static void encrypt(InputStream is, OutputStream os) throws Exception {
		//将读取的文件加密
		int x;
		while ((x = is.read()) != -1) {
			os.write(x ^ 0xff);
		}
	}
	
	public static void main(String[] args) throws Exception {
		//主方法接收两个参数, 源文件和目标文件夹
		String src = args[0];
		String destDir = args[1];
		
		//要加密的文件的名字
		String fileName = src.substring(src.lastIndexOf("\\") + 1);
		//指定要写出的文件
		String dest = destDir + "\\" + fileName;
		
		InputStream is = new FileInputStream(src);
		OutputStream os = new FileOutputStream(dest);
		
		//执行加密方法
		encrypt(is, os);
		is.close();
		os.close();
		/*
		 * 将原来的Test1.class文件用加密后的Test1.class文件覆盖, 这样加载器就不能加载到这个文件了,
		 * 这时候需要自定义一个加载器来将这个.class文件先解密, 然后通过反射来获得正确的结果
		 */
	}
	
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		//将传进来的类名加上路径和.class后缀
		String classFileName = classDir + "\\" + name + ".class";
		try {
			//将文件读入输入流
			InputStream is = new FileInputStream(classFileName);
			//文件写出到字节输出流
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			//将文件解密
			encrypt(is, baos);
			is.close();
			
			byte[] data = baos.toByteArray();
			//根据写出的数据返回Class文件
			return defineClass(data, 0, data.length);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return super.findClass(name);
	}
}

 

//测试自定义类加载器
package cn.itcast.classloader;

import javax.xml.crypto.Data;

public class MyClassLoaderTest {
	public static void main(String[] args) throws Exception {
		// 利用自定义的加载器加载加密的文件得到Class
		Class clazz = new MyClassLoader("itcast").findClass("Test1");
		// 生成对象的实例
		clazz.newInstance();
	}
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值