【问题标题】:which classloader uses for composition classes哪个类加载器用于组合类
【发布时间】:2014-06-16 14:48:51
【问题描述】:

分析以下代码:

public class A {
    public void foo() {
        B b = new B();  // row#1
        b.toString();  
}

据我了解,row#1 类中的类加载器由类 A 的类加载器加载。

考虑类B

class B {
   C c = new C();
}

请说明将使用哪个类加载器来加载类C

更新

在我获得B 类的类加载器并编写以下代码后:

classloaderOfClassB.loadClass("A")

请说明所有涉及的类将使用什么类加载器。

【问题讨论】:

  • 也许类加载器“知道”C。因此,这在很大程度上取决于您的环境。还是您将“类加载”与“对象实例化”混淆了?
  • @Gyro Gearless 我不会混淆类加载和实例化
  • @Gyro Gearless “了解”C 的类加载器如何检测这个类加载器?

标签: java osgi classloader


【解决方案1】:

OSGi 将使用 B 类的类加载器来加载 C 类。例如,如果 B 和 C 位于同一个包中,但 C 位于内部包中,它仍然可以工作。原因是当类 B 由类 A 的类加载器加载时,它将委托给 B 所在的捆绑包的类加载器。所以 B 将被加载它所在的包的类加载器。

【讨论】:

    【解决方案2】:

    如果一个类依赖于其他类,例如在您的示例中,类 A 依赖于本身依赖于类 C 的类 B,并且这些类尚未加载,则当前类的类加载器将用于尝试加载依赖的类。

    事实上,对于你的例子,A​​ 类的类加载器也将用于加载 B 类和 C 类。

    声明

    classloaderOfClassB.loadClass("A")
    

    现在将加载类 A 并将类加载器设置为 classloaderOfClassB 引用的实例。然后,同一个类加载器将用于加载 A 类中所有其他尚未加载的依赖项。由于 B 类已经由同一个加载器加载,所以一切都很好。

    这种机制确保类加载在以下场景中运行良好:

    考虑有一个可插入的应用程序,其中插入意味着将 JAR 文件(不是类路径的一部分)放入指定的目录。然后,您使用由 JAR 文件(当然是 URL 形式)构建的 URLClassLoader 加载这个新 JAR 的类和资源。由于所有类现在都将这个URLClassLoader 作为它们的类加载器,所有进一步的依赖项都将由同一个URLClassLoader 加载,这是正确的,因为只有这个URLClassLoader 会查看这个JAR 文件。

    【讨论】:

      【解决方案3】:

      我使用下面的示例生成以下输出。

      在不知道类 C 的位置的情况下,我假设它位于 A 中。如果没有,此堆栈跟踪应该可以帮助您。

      AFAIK,A 加载 C

      输出

      java.lang.Thread.getStackTrace(Thread.java:1568)
      A$C.<init>(Main.java:15)
      A$B.<init>(Main.java:10)
      A.foo(Main.java:5)
      A.main(Main.java:23)

      示例

      import java.lang.StackTraceElement;
      
      class A {
          public void foo() {
              B b = new B();  // row#1
              b.toString();  
          }
      
          class B {
              C c = new C();
          }
      
          class C {
              public C() {
                  for (StackTraceElement ele : Thread.currentThread().getStackTrace()) {
                      System.out.println(ele);
                  }
              }
          }
      
          public static void main (String[] args) {
              A a = new A();
              a.foo();
          }
      }
      

      【讨论】:

      • 我在哪里可以看到堆栈跟踪中的类加载器 ID?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      • 2013-12-17
      • 1970-01-01
      相关资源
      最近更新 更多