我怎么知道当前的java中的classLoader

nai*_*fei 4 java jvm classloader

我正在学习加载Java类的过程,遇到一些困惑。

我知道加载Java类时当前classLoader不会直接加载Java类,它将委托给其父classLoader(一个递归过程),直到其父不能加载此类为止。


问题是当前的classLoader是什么? 引导程序?延期?应用程式?
如何获取当前的classLoader?而且我知道有一个API:

xxx.Class.getClassLoader();
Run Code Online (Sandbox Code Playgroud)

但我不确定返回值是否为currentClassLoader。我认为应该是实际加载此java类的classLoader 。

为了更详细地描述我的问题,我将举一个例子。
我在博客中获得了以下内容。

ThreadContextClassLoader用于处理Java SPI,接口在Java中定义core lib并由Bootstrap ClassLoader加载,第三方实现这些接口,然后由AppClassLoader加载jar
解决方案:传统的classLoader无法处理这种情况,因为它无法发现第三方jar当我们在核心库中使用第三方工具时。

我能理解的大多数上述方法都使我感到困惑:例如,接口CoreA和类CoreB在Java中core lib,应由Bootstrap ClassLoader加载,而AImpl是由第三方实现的A的实现,并应由以下方法加载AppClass加载器

代码段如下:

 public Interface CoreA{
     void add();
 }

 public Interface AImpl implements CoreA{
     void add(){};
 }

 public class B{
      public void demo(){
         a = new AImpl();
      }
 }
Run Code Online (Sandbox Code Playgroud)

那么,如果我们参考Bmain method,那么我们将加载B,因为类加载器B引导则关于AImpl当前装载机是引导所以它不能被发现的?我不知道这是否是我的猜测?

任何建议将被认真考虑。

dmi*_*ony 5

一般来说,您是正确的,找不到它。让我向您展示以下示例。比方说,我们有3类:ABMain这样的:

public class A {
    public String a() {
        return "a";
    }
}

public class B {
    public String b() {
        return new A().a();
    }
}

public class Main {
    public static void main(String... args) {
        System.out.println(new B().b());
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,将这些类打包到相应的jars中a.jarb.jarMain.class放入工作目录中。之后,让我们测试以下方案:

1)拍卖(A.classB.classMain.class)被加载system classloader并正常工作:

$ java -cp .:a.jar:b.jar Main
a
Run Code Online (Sandbox Code Playgroud)

2)B.classsystem classloaderA.class加载,bootstrap classloader并且一切仍然可以正常进行,因为system classloader委托加载到了bootstrap classloader(只是因为bootstrap classloader可以加载):

$ java -Xbootclasspath/a:a.jar -cp .:b.jar Main
a
Run Code Online (Sandbox Code Playgroud)

3)A.classsystem classloaderB.classbootstrap classloader(您的情况)加载。在这种情况下,B.class当前classloader的加载过程为bootstrap classloader,但找不到B.class并失败:

$ java -Xbootclasspath/a:b.jar -cp .:a.jar Main
Exception in thread "main" java.lang.NoClassDefFoundError: A
        at B.b(B.java:4)
        at Main.main(Main.java:4)
Run Code Online (Sandbox Code Playgroud)

让我们更仔细地看看最后一个例子。这里发生了什么事:

  1. 尝试使用public static main(String[] args)方法查找类

    1.1。system classloader尚未加载,因此委托给extension classloader

    1.2。extension classloader尚未加载,因此委托给bootstrap classloader

    1.3。bootstrap classloader尚未加载并尝试加载,无法加载并将控制权返回给extension classloader

    1.4。extension classloader尝试加载,无法加载并将控制权返回给system classloader

    1.5。system classloader负载Main.class

  2. Main.class已处理,我们尝试B.class使用当前的类加载器加载system classloader

    2.1。system classloader尚未加载,因此委托给extension classloader

    2.2。extension classloader尚未加载,因此委托给bootstrap classloader

    2.3。bootstrap classloader尚未加载并加载B.class

  3. B.class已处理,我们尝试A.class使用当前的类加载器加载bootstrap classloader

    3.1。bootstrap classloader尚未加载,并尝试加载并失败

希望对您有帮助。

  • 感谢您的贡献。它对我有很大的帮助。但我认为**第 2 节**存在一个小缺陷“因为如果无法加载类本身,系统类加载器会将加载委托给引导类加载器”。_系统类加载器_将加载委托给_其父类加载器_并不是因为它无法加载类本身。仅当其_parent classloader_无法处理加载java类时,_current class_才会尝试加载类本身。 (2认同)

nai*_*fei 1

“当前类加载器”是引用它的类的真实类加载器(实际上加载该类)。

例如,如果的classLoaderclass Aext classloaderclass A引用 class B C D。那么“当前类加载器”B C D就是ext classLoader。当然,主类的“当前类加载器”是System classLoader