现在的位置: 首页 > 综合 > 正文

java里Class类的forName方法和ClassLoader的loadClass方法的实验

2018年01月16日 ⁄ 综合 ⁄ 共 1842字 ⁄ 字号 评论关闭

我们在学习JVM的一个类加载体系的时候,应该会学到这样一个名词“双亲委托模式”。而当我们跟踪ClassLoader里的loadClass方法,也可以很清楚的看到这种算法的具体实现。但是当我们跟踪Class.forName方法时,没有发现这种算法,只是有一个ClassLoader.getCallerClassLoader()这样的方法来获取ClassLoader?那我的问题来了,这两种方法所加载的类,可以让JVM找到吗?

我们知道,要让一个类可以运行,需要将些类转化为Class对象,而且这个对象必需可以让JVM找到,这样我们才可以使用。有一种说法是这样的,需要同一个类加载器加类的类才能使用,其实我认为这种说是不准确的,其实哪个类加载器加载类都无谓的,举个反例,就是String类是由Bootstrap启动类加载器加载的(我们可以用String.class.getClassLoader()来输出它的加载器,可以发现输出的结果是null,所以表明它是Bootstrap启动的),而我们调用String的类并不是Bootstrap加载的,那我们的类岂不是不能用String类,显示答案是可以用的,这就说明跟哪个类加载器加载类是没有关系的,只要按JVM的算法让JVM可以找到此类的Class对象就可以了,所以回到上面的问题,这两种加载方法,产生的结果是一样的吗?下面我做了一个实验,我想是可以证明到,它们是一样的:

1、创建一个类ClazzLoaderClass.java,它的作用就是打印一条信息。

package xxx.com;

public class ClazzLoaderClass {
	public ClazzLoaderClass(){ 
		System.out.println("clazz loader load class");    
	}
}

2、我们再创建一个类ClazzForName.java,它的作用就是打印出一条信息,并且调用了上面的ClazzLoaderClass.java类。

package xxx.com;

public class ClazzForName {
	public ClazzForName(){
		System.out.println("clazz for name");
		new ClazzLoaderClass();
	}  
}

3、写一个main方法。每句的代码的作用,如下面的注析。需要注意的是,我们会在加载完ClazzLoaderClass类后,删除ClazzLoaderClass.class文件;在加载完ClazzForName类后,将ClazzForName.class从硬盘中删除。

package xxx.com;

public class TestLoader {
	public static void main(String[] args) throws Exception{
		ClassLoader loader = TestLoader.class.getClassLoader();//获取main所在类的ClassLoader
		loader.loadClass("xxx.com.ClazzLoaderClass");//加载ClazzLoaderClass
		System.out.println("ClazzLoaderClass类加载完成-------------------------");
		Thread.sleep(15000);//在这个15秒里,我们会删除ClazzLoaderClass.java这个类
		Class.forName("xxx.com.ClazzForName");//加载ClazzForName
		System.out.println("ClazzForName类加载完成-------------------------");
		Thread.sleep(15000);//在这个15秒里,我们会删除ClazzForName.java这个类
		new ClazzForName();//执行
	}
}

4、运行后的结果如下:

ClazzLoaderClass类加载完成-------------------------
ClazzForName类加载完成-------------------------
clazz for name
clazz loader load class

结论:

1、这说明不管用forName还是loadClass,它们之间都是可以互相访问。因为我们在执行new之前,就将两个class文件都删除了。

抱歉!评论已关闭.