`
毕竟红尘
  • 浏览: 12827 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

证明:同一个JVM里面一个Class可以被load多次

阅读更多

    对CLASSLOADER有过研究的人都知道,JVM使用CLASSLOADER在JVM中分隔出许多命名空间,不同的命名空间中的类是不“互见的”,这个“不互见”的意思是彼此不知道对方的存在,比如classloader1加载类A,在classloader2所构建的命名空间里面类就不知道的。classloader2因为不知道classloader2加载了A,所以它自己也可以以自己的方式来加载“另一个”类A。这样其实,在JVM内就存在两个Class A了。、

    上面的理论其实在看过“深入JVM”后就知道了。最近又翻了翻这本书,想起两年前与同事说的那句话“JVM可以loader两个同样的类,那你证明下呀”,当时没当回事,反正也是懵懵懂懂证明不了,避而不谈。现在呢,有时间也有能力了,那就来证明下吧。

     这个证明的逻辑是:

    因为class在被加载的时候,其static域会被初始化,那么一个类被加载两次加载进jvm的话,那么static域就会被初始化两次。

    那现在只要证明static的域是可以被初始化两次就可以了。那怎么证明呢?

    只要每次在初始化的时候能给static域赋上不同的值,区分出来,在特定的时候打印出来

就可以了。

    看下下面的代码片段,事情可能就清楚了。

    被加载的类 IntProducer:
  
import java.util.Random;

  public class IntProducer
  {
        //用随机值来加载静态域赋值,如果被加载两次age应该会是不同的值
	public static int age = getRandom();

	public static int getRandom()
	{
		Random ran = new Random(System.nanoTime());
		int rand = ran.nextInt(10);
		System.out.println("IntProducer 被加载,产生随机数:"+rand);
		return rand;

	}

 }


   用于加载IntProducer的类:


 
public class LoaderSample4
{

	public static void main(String[] args) throws Exception
	{
	    System.out.println(LoaderSample4.class.getClassLoader());
		
		
		URL[] us =
		{ new URL("file://D:/") };

		ClassLoader loader1 = new URLClassLoader(us);
		Class c1 = loader1.loadClass("IntProducer");

		System.out.println(c1.getClassLoader()+":"+c1.getField("age").getInt(c1));

		//再加载一次
		ClassLoader loader2 = new URLClassLoader(us);
		Class c2 = loader2.loadClass("IntProducer");
		System.out.println(c2.getClassLoader()+":"+c2.getField("age").getInt(c2));

	}

}



  

     
   
   

   
分享到:
评论
3 楼 Firklaag 2010-08-09  
确实是两个类,,但是为什么只初始化一次?
2 楼 wu_quanyin 2010-06-13  
sun.misc.Launcher$AppClassLoader@19821f
IntProducer 被加载,产生随机数:5
sun.misc.Launcher$AppClassLoader@19821f:5
sun.misc.Launcher$AppClassLoader@19821f:5

这是我执行的结果,,,加载一次????
1 楼 sword_ljx 2009-01-08  
在一个JVM里,两个Class是否相同不能通过通过它的名字(package+classname)相等来决定。
你的例子里,相同是Class的二进制表示,通过两个不同的CL加载之后这两个类已经不一样。
所以,是两个类,而不是一个类。

引用jvm spec(2nd)的一段话:
At run time, a class or interface is determined not by its name alone, but by a pair: its fully qualified name and its defining class loader. Each such class or interface belongs to a single runtime package. The runtime package of a class or interface is determined by the package name and defining class loader of the class or interface.



相关推荐

Global site tag (gtag.js) - Google Analytics