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

标签 java jvm classloader

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

我知道在加载 java 类 时,current classLoader 不会直接加载 java 类,它会委托(delegate)给它的 parent classLoader(一个递归过程)直到它的父类无法加载这个类。


问题是:当前的classLoader是什么? Bootstrap?扩大?应用?
如何获取当前的classLoader? 我知道有一个 API:

xxx.Class.getClassLoader();

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

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

ThreadContextClassLoader is used to deal with java SPI, Interface is defined in java core lib and loaded by Bootstrap ClassLoader and third party implement these interface then the jar are loaded by AppClassLoader
Solution: traditional classLoader cant deal with this case,because it cant discovery the third party jar when we use the third party implement in core lib.

我能理解上面的大部分内容,但解决方案让我感到困惑: 例如,接口(interface) 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();
      }
 }

那么如果我们在main方法中引用B,那么我们将加载B,因为类加载器 BBootstrap那么关于AImpl当前的Loader是Bootstrap所以找不到? 不知道是不是我猜的那样?

任何建议将不胜感激。

最佳答案

一般来说你是对的,是找不到的。让我向您展示以下示例。假设我们有 3 个类:A , BMain像这样:

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());
    }
}

然后我们将这些类打包到对应的 jar 中:a.jar , b.jar并放置 Main.class进入工作目录。之后让我们测试以下场景:

1) 所有内容( A.class , B.class , Main.class )都由 system classloader 加载并且工作正常:

$ java -cp .:a.jar:b.jar Main
a

2) B.classsystem classloader 加载和 A.classbootstrap classloader 加载一切仍然正常,因为 system classloader代表正在加载到 bootstrap classloader (仅仅因为 bootstrap classloader 可以加载它):

$ java -Xbootclasspath/a:a.jar -cp .:b.jar Main
a

3) A.classsystem classloader 加载和 B.classbootstrap classloader 加载(你的情况)。在这种情况下,在加载 B.class 期间当前类加载器是 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)

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

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

    1.1。 system classloader还没有加载它所以委托(delegate)给 extension classloader

    1.2。 extension classloader还没有加载它所以委托(delegate)给 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还没有加载它所以委托(delegate)给 extension classloader

    2.2。 extension classloader还没有加载它所以委托(delegate)给 bootstrap classloader

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

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

    3.1。 bootstrap classloader还没有加载它并尝试加载和 失败

希望对您有所帮助。

关于java - 我怎么知道java中当前的classLoader,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41102617/

相关文章:

Java 类转换异常,使用 javax xml 提供程序时出现类加载器错误?

java - 如何在其运行方法完成后清理线程?

java - 二分查找和对两个数组使用 SortKey - 非常详细 [Java]

Java 6 Hotspot 中的 Java 5 运行时

java - java中的对象堆总是没有足够的空间

logging - Log4j:每个 war 一个日志文件

java - 如果找不到我要返回的对象,我应该从方法中返回什么?

java - 当我修改 BeanUtils.CopyProperties 的目标对象时,源代码被修改

java - 为Web应用程序设置指定的系统属性

java - 将文件夹添加到 RCP 产品中的类路径