不同类加载器加载同一个class文件

电玩女神 2022-12-16 06:12 259阅读 0赞

不同类加载器加载同一个class文件得到的类型也是不同的。

验证如下:

D:\\00-test目录下,有名为Test.class的文件,其编译前的源码如下:

  1. public class Test {
  2. public static int count = 0;
  3. public Test() {
  4. ++count;
  5. System.out.println(this.getClass().getClassLoader());
  6. System.out.println("count: " + count);
  7. }
  8. }

每当创建一个对象的时候,静态变量count就会自增,可以利用count的值来判定不同类加载器得到的Class对象是否是同一个。

创建Main类如下:

  1. public class Main {
  2. public static void main(String[] args) throws Exception {
  3. URLClassLoader loader_1 =
  4. new URLClassLoader(new URL[]{new File("D:\\00-test").toURI().toURL()});
  5. URLClassLoader loader_2 =
  6. new URLClassLoader(new URL[]{new File("D:\\00-test").toURI().toURL()});
  7. Class<?> clazz_1 = loader_1.loadClass("Test");
  8. clazz_1.newInstance();
  9. Class<?> clazz_2 = loader_2.loadClass("Test");
  10. clazz_2.newInstance();
  11. }
  12. }

main()方法中,首先自定义两个类加载器,分别使用这两个类加载器加载Test.class文件,然后使用得到的Class对象创建实例,最后得到结果如下:

  1. java.net.URLClassLoader@1b6d3586
  2. count: 1
  3. java.net.URLClassLoader@74a14482
  4. count: 1

可以看到,两个对象的类加载器并不相同,count值却是相同的,这说明这两个实例虽然都是从Test.class中得来,类型却并不相同,从而count只自增一次。

实际上,在jvms8的5.3.2节有这样一段阐述:

  1. At run time, a class or interface is determined not by its name alone, but by a pair:
  2. its binary name 4.2.1) and its defining class loader. Each such class or interface
  3. belongs to a single run-time package. The run-time package of a class or interface is
  4. determined by the package name and defining class loader of the class or interface.

翻译如下:
在运行时,一个类或者接口并不是单单由它的名称确定的,而是由它的二进制名称以及它的定义类加载器共同确定的。
每个这样的类或者接口都属于一个运行时包,运行时包则由包名和定义类加载器共同确定。

上述中所谓的定义类加载器实际上就是getClassLoader()的返回值,而这个概念的产生则跟类加载过程中的“双亲委派机制”有关。

当要加载一个类时,第一个发起类加载的加载器称之为“初始类加载器”(initiating loader),但是根据“双亲委派机制”,它会先将加载委派给父加载器,如果父加载器加载失败,才会最终由自己尝试加载。而无论哪个加载器加载成功,它就是该类的定义类加载器(defining class loader)。

参考:https://www.cnblogs.com/SanjiApollo/p/12839682.html

发表评论

表情:
评论列表 (有 0 条评论,259人围观)

还没有评论,来说两句吧...

相关阅读

    相关 class文件过程

    1、在加载class文件的时候,JVM会先加载类中的所有静态成员( 方法,变量,静态代码块 )都加载到方法区class文件的所处静态区中 2、当把所有的静态成员加载完成之后,