初探JVM-ClassLoader源码(三)

2014-11-24 08:20:04 · 作者: · 浏览: 6
e class : " + (c1 == c2)); console:

They are same class : true

两个Object用==比较,返回true,就是两者的地址相等,就说明是同一个Object。因此我们能看出,同名的class在JVM只会加载一次,所以两者相等。

但是如果用URLClassLoader加载外面的类Ext4Test,效果却不一样:

        String url = "file:/" + System.getProperty("user.dir") +"/newClass/";
        URLClassLoader ucl1 = new URLClassLoader(new URL[]{new URL(url)});
        URLClassLoader ucl2 = new URLClassLoader(new URL[]{new URL(url)});
        Class
   c1 = ucl1.loadClass("com.jscai.classloader.Ext4Test");
        Class
   c2 = ucl2.loadClass("com.jscai.classloader.Ext4Test");
        System.out.println("They aresame class : " + (c1 == c2));

console:

They are same class : false

虽然类名是一样的,但是使用的类加载器实例不同,所以JVM不认为这俩是同一个class,两者就不想等了。而上个例子中,两个Inner4Test的class相等,是因为JVM的类加载实例都是单例,同名和同加载器实例的两个条件都符合了。

同样我们可以把类加载器实例换成一样的,两个class就相等了:

        URLClassLoader ucl1 = new URLClassLoader(new URL[]{new URL(url)});
        Class
   c1 = ucl1.loadClass("com.jscai.classloader.Ext4Test");
        Class
   c2 = ucl1.loadClass("com.jscai.classloader.Ext4Test");
        System.out.println("They aresame class : " + (c1 == c2));

console:

They are same class : true

因此,根据这个特点,我们可以自定义类加载器,来实现动态加载类(装载):一方面管理好现有的实例对象,另一方面监听是否有jar更新,如果有更新就重新生成加载器实例去加载这些class,这样新的class就能代替旧的class,就能实现动态加载而避免整体重启了。例如Tomcat的热部署。 (当然,具体实现还是很复杂的,没有我说的那么简单!)

---- 源码参考JDK-7