jvm自定义类的加载器

1. 创建用户自定义的类加载器:

要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定的类的名字,返回对应的Class对象的引用。


2. 自定义类加载器:

MyClassLoader.java   该例子主要用来验证父类委托机制!

public class MyClassLoader extends ClassLoader {
	private String name; // 类加载器的名字
	private String path = "d:\\"; // 加载类的路径
	private final String fileType = ".class"; // class文件的扩展名

	public MyClassLoader(String name) {
		super(); // 让系统类加载器成为该类加载器的父加载器
		this.name = name;
	}

	public MyClassLoader(ClassLoader parent, String name) {
		super(parent); // 显式指定该类加载器的父加载器
		this.name = name;
	}

	@Override
	public String toString() {
		return this.name;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	@Override
	public Class<?> findClass(String name) throws ClassNotFoundException {
		// 重写的时候把protected改为public
		// 获取字节数组
		byte[] data = this.loadClassData(name);
		// 将字节数组转换成Class对象返回
		return this.defineClass(name, data, 0, data.length);
	}

	/**
	 * 得到class文件的二进制字节数组
	 *
	 * @param name
	 * @return
	 */
	private byte[] loadClassData(String name) {
		InputStream is = null;
		byte[] data = null;
		ByteArrayOutputStream baos = null;
		try {
			// 将完整类名中的.转化成\
			name = name.replace(".", "\\");
			is = new FileInputStream(new File(path + name + fileType));
			baos = new ByteArrayOutputStream();
			int ch = 0;
			while (-1 != (ch = is.read())) {
				baos.write(ch);
			}
			data = baos.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
				baos.close();
			} catch (Exception e2) {
			}
		}
		return data;
	}

	// main方法用来测试
	public static void main(String[] args) throws Exception {
		MyClassLoader loader1 = new MyClassLoader("loader1");
		// loader1的父加载器是系统类加载器
		// 系统类加载器会在classpath指定的目录中加载类
		loader1.setPath("d:\\myapp\\serverlib\\");

		MyClassLoader loader2 = new MyClassLoader(loader1, "loader2");
		// 将loader1作为loader2的父加载器
		loader2.setPath("d:\\myapp\\clientlib\\");

		MyClassLoader loader3 = new MyClassLoader(null, "loader3");
		// loader3的父加载器是根类加载器
		loader3.setPath("d:\\myapp\\otherlib\\");

		// 测试加载
		test(loader2);
		test(loader3);
		// 测试不同命名空间的类的互相访问
		test2(loader3);
	}

	public static void test(ClassLoader loader) throws Exception {
		Class clazz = loader.loadClass("Sample");
		Object object = clazz.newInstance();
	}

	public static void test2(ClassLoader loader) throws Exception {
		Class clazz = loader.loadClass("Sample");
		Sample object = (Sample) clazz.newInstance();
		System.out.println("sample v1: " + object.v1);
	}
}
Sample.java
public class Sample {
    public int v1 = 1;
    public Sample() {
        System.out.println("Sample is loaded by: " + this.getClass().getClassLoader());
        // 主动使用Dog类
        new Dog();
    }
}
Dog.java
public class Dog {
    public Dog() {
        System.out.println("Dog is loaded by: " + this.getClass().getClassLoader());
    }
}





test3方法中,MyClassLoader类由系统类加载器加载,而Sample类由loader3类加载器加载,因此MyClassLoader类看不见Sample类。

在MyClassLoader类的main()方法中使用Sample类会导致错误。

当两个不同命名空间内的类互相不可见时,可采用Java反射机制来访问对方实例的属性和方法,即反射可以突破命名空间的限制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值