对CLASSLOADER有过研究的人都知道,JVM使用CLASSLOADER在JVM中分隔出许多命名空间,不同的命名空间中的类是不“互见的”,这个“不互见”的意思是彼此不知道对方的存在,比如classloader1加载类A,在classloader2所构建的命名空间里面类就不知道的。classloader2因为不知道classloader2加载了A,所以它自己也可以以自己的方式来加载“另一个”类A。这样其实,在JVM内就存在两个Class A了。、
上面的理论其实在看过“深入JVM”后就知道了。最近又翻了翻这本书,想起两年前与同事说的那句话“JVM可以loader两个同样的类,那你证明下呀”,当时没当回事,反正也是懵懵懂懂证明不了,避而不谈。现在呢,有时间也有能力了,那就来证明下吧。
这个证明的逻辑是:
因为class在被加载的时候,其static域会被初始化,那么一个类被加载两次加载进jvm的话,那么static域就会被初始化两次。
那现在只要证明static的域是可以被初始化两次就可以了。那怎么证明呢?
只要每次在初始化的时候能给static域赋上不同的值,区分出来,在特定的时候打印出来
就可以了。
看下下面的代码片段,事情可能就清楚了。
被加载的类 IntProducer:
用于加载IntProducer的类:
上面的理论其实在看过“深入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));
}
}