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)
那么,如果我们参考B
的main method
,那么我们将加载B
,因为类加载器的B
是引导则关于AImpl
当前装载机是引导所以它不能被发现的?我不知道这是否是我的猜测?
任何建议将被认真考虑。
一般来说,您是正确的,找不到它。让我向您展示以下示例。比方说,我们有3类:A
,B
和Main
这样的:
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.jar
,b.jar
并Main.class
放入工作目录中。之后,让我们测试以下方案:
1)拍卖(A.class
,B.class
,Main.class
)被加载system classloader
并正常工作:
$ java -cp .:a.jar:b.jar Main
a
Run Code Online (Sandbox Code Playgroud)
2)B.class
由system classloader
和A.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.class
由system classloader
和B.class
由bootstrap 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)
让我们更仔细地看看最后一个例子。这里发生了什么事:
尝试使用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
Main.class
已处理,我们尝试B.class
使用当前的类加载器加载system classloader
2.1。system classloader
尚未加载,因此委托给extension classloader
2.2。extension classloader
尚未加载,因此委托给bootstrap classloader
2.3。bootstrap classloader
尚未加载并加载B.class
B.class
已处理,我们尝试A.class
使用当前的类加载器加载bootstrap classloader
3.1。bootstrap classloader
尚未加载,并尝试加载并失败
希望对您有帮助。
“当前类加载器”是引用它的类的真实类加载器(实际上加载该类)。
例如,如果的classLoaderclass A
是ext classloader并class A
引用 class B C D
。那么“当前类加载器”B C D
就是ext classLoader。当然,主类的“当前类加载器”是System classLoader。
归档时间: |
|
查看次数: |
5426 次 |
最近记录: |