![](/img/trans.png)
[英]Can I get an instance of a class in Java during runtime if I know its ClassLoader (ClassLoader Namespace)
[英]how can I know the current classLoader in java
我正在學習加載Java類的過程,遇到一些困惑。
我知道在加載Java類時 , 當前的classLoader不會直接加載Java類 ,它將委托給其父classLoader (一個遞歸過程),直到其父不能加載該類為止。
問題是 : 當前的classLoader是什么? 引導程序? 延期? 應用程式?
如何獲取當前的classLoader? 而且我知道有一個API:
xxx.Class.getClassLoader();
但我不確定返回值是否為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();
}
}
然后,如果我們引用B
在main method
,那么我們將加載B
因為類裝載程序 B
是自舉然后大約AImpl
當前Loader是自舉所以它不能找到? 我不知道這是否是我的猜測?
任何建議將被認真考慮。
一般來說,您是正確的,找不到它。 讓我向您展示以下示例。 假設我們有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());
}
}
然后將這些類打包到相應的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.class
由system classloader
而A.class
由bootstrap classloader
並且一切仍然正常,因為system classloader
將system classloader
委托給bootstrap classloader
(只是因為bootstrap classloader
可以加載):
$ java -Xbootclasspath/a:a.jar -cp .:b.jar Main
a
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)
讓我們更仔細地看看最后一個例子。 這里發生了什么事:
嘗試使用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
加載system classloader
加載Main.class
Main.class
已處理,我們嘗試使用當前的classloader system classloader
加載B.class
2.1。 system classloader
尚未加載,因此委托給extension classloader
2.2。 extension classloader
尚未加載,因此委托給bootstrap classloader
2.3。 bootstrap classloader
尚未加載並加載B.class
B.class
已處理,我們嘗試使用當前的類加載器bootstrap classloader
加載A.class
3.1。 bootstrap classloader
尚未加載,並嘗試加載並失敗
希望對您有幫助。
“當前類加載器”是引用它的類的真實類加載器 ( 實際加載該類)。
例如,如果class A
的classLoader是ext classloader,而class A
引用類BCD
。 那么BCD
的“當前類加載器”是ext classLoader 。 當然, 主類的“當前classLoader”是System classLoader 。
當類A嘗試加載另一個類B時,加載A的ClassLoader是當前的ClassLoader。 當前一詞含糊地指的是執行上下文-例如,如何最終觸發當前類加載調用的方法。
沒有方法(例如getCurrentClassLoader
)簡單地給出當前的ClassLoader,但是有一些api方法在內部使用當前的ClassLoader的概念。 例如, Class.forName(String className)
如果檢查該方法的實現方式,它將告訴您“當前類加載器”的含義:
public static Class<?> forName(String className) throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
如果可以掌握Class實例,則始終可以通過調用Class::getClassLoader()
方法來請求其背后的加載器。 那將是您當前的類加載器。 但是,棘手的一點是,確定加載程序是引導程序,擴展程序還是系統類加載程序。 棘手的原因是它是特定於實現的,並且您始終可以實現自己的類加載機制。
@dmitrievanthony給出的示例說明了事情如何變得真正復雜。 這是JNDI面臨的類似情況,也是引入Thread.getContextClassLoader()
的原因。 在這里了解更多
引用文章中最相關的文章:
...根據定義,當前的類加載器將加載並定義當前方法所屬的類。 當類之間的動態鏈接在運行時解析時,以及使用Class.forName(),Class.getResource()和類似方法的單參數版本時,將暗含該類加載器。 X.class類文字等語法構造也使用它...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.