[Java]ClassLoader

在Java程序员的角度来看有三种类加载器:

  • bootstrap:加载JAVA_HOME/lib目录下的类
  • extension:加载JAVA_HOME/lib/ext目录下的类
  • application:加载classpath指定目录中的类
在JVM中,根据ClassLoader来决定是不是同一个类,从这个角度来看,ClassLoader的作用类似namespace,也就是说可以利用ClassLoader对Class进行隔离。而如果这么用可能就要破坏双亲委派模式了。

双亲委派

从代码里面看双亲委派模型更直观些:
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
	// 首先检查是否加载过该类
	Class c = findLoadedClass(name);
	if (c == null) {
		// 先让parent去加载
		try {
			if (parent != null) {
				c = parent.loadClass(name, false);
			} else {
				c = findBootstrapClassOrNull(name);
			}
		} catch (ClassNotFoundException e) {
		}
		// 如果parent没有加载到,自己再去加载
		if (c == null) {
			c = findClass(name);
		}
	}
	if (resolve) {
		resolveClass(c);
	}
	return c;
}
自己定义ClassLoader的话可以实现findClass方法:
protected Class<?> findClass(String name) {
	// 加载不是我们关心的类时,按照原来的逻辑走
	if (name.startsWith("java")) {
		try {
			return super.loadClass(name);
		} catch (ClassNotFoundException e) {
		}
	}
	// 从dir/XXX.class文件读取数据
	byte[] data = loadClassData(name);
	// 根据byte[]生成Class
	return defineClass(name, data, 0, data.length);
}
下面对自己写的ClassLoader进行测试:
public class Main {
	public static void main(String[] args) throws Exception {
		MyClassLoader loaderA = new MyClassLoader();
		MyClassLoader loaderB = new MyClassLoader();
		Class<?> classA = loaderA.findClass("TestClass");
		Class<?> classB = loaderB.findClass("TestClass");
		System.out.println(classA == classB);// false
	}
}
可以看到不同的两个ClassLoader加载相同的Class,在JVM中判断为不是同一个类。这样可能导致一个问题:用Grovy等工具的时候用ClassLoader加载类,可能会有大量的ClassLoader加载大量的类并没有被及时回收导致OOM。

命名空间

由不同的类装载器加载的类被放在虚拟机内部不同的命名空间中。同一个命名空间中的类可以直接进行交互,而不会感知到另一个命名空间中类的存在。这里有两个概念:
  • 初始类装载器:如果要求A去装载一个类型,而A返回了B装载的类型,那么A为就是初始类装载器。
  • 定义类装载器:B是定义类装载器。
如果某个类加载器把加载的任务委派给另一个类加载器,而后者定义了这个类型,那么被委派的类加载器装载的这个类型,在所有被记为该类型的初始类装载器的命名空间中共享。

----------END----------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值