Re: [問題] ClassLoader的一個問題[已解決]
※ 引述《del680202 (HANA)》之銘言:
: 今天在寫程式的時候
: 我希望讓我程式有類似plug-in的功能
: 所以我試著用URLClassLoader去實作這個功能
: 首先我測試了一下
: 先用eclipse開了一個project A
: 裡面一個interface
: interface CLI2 {
: public String say();
: }
: 而存在一個class 去實作他
: public class CLTest implements CLI2 {
: static{
: System.out.println("Now!Class Load!");
: }
: @Override
: public String say() {
: System.out.println("Hello I am a happy boy!");
: return "Hello";
: }
: }
: 我把他輸出成tester.jar
: 之後我再開了一個project B
: 裡面是引用他的程式碼
: URL url1 = new URL("file:c:/TC/");
"file:c:/TC/tester.jar"
: URLClassLoader urlClassLoader1 =
: new URLClassLoader(new URL[] {url1}
: ,Thread.currentThread().getContextClassLoader());
: Class c2 = urlClassLoader1.loadClass("CLTest");
: Object o=c2.newInstance();
: CLI2 ci=(CLI2)o;
: ci.say();
: -----------------------------
: Project B裡面有隻相同的inteface CLI2,他是希望用來轉型
: 跑下去後出現了error
: Exception in thread "main" java.lang.IllegalAccessError:
: class CLTest cannot access its superinterface CLI2
: 上網查了一下原因,似乎是因為當前的classLoader沒辦法存取他的interface
到這邊, 把 CLI2 宣告成 public 應該就可以解決問題了.
: 我把程式作了修改,URLClassLoader第二個參數改成null
: URL url1 = new URL("file:c:/TC/");
: URLClassLoader urlClassLoader1 =
: new URLClassLoader(new URL[] {url1}
: ,null);
: Class c2 = urlClassLoader1.loadClass("CLTest");
: Object o=c2.newInstance();
: CLI2 ci=(CLI2)o;
: ci.say();
: 雖然解決了第一個問題卻延伸出另一個問題
: 在CLI2 ci=(CLI2)o;的地方出現轉型錯誤的exception
: Exception in thread "main" java.lang.ClassCastException:
: CLTest cannot be cast to CLI2
: 後來上網查了一下資料 才知道他型別判定是除了class name跟package name
: 還包括ClassLoader,我的CLI2是AppClassLoader載入的
: o則是我創造的URLClassLoader載入的
實際上, CLI2 被 load 兩次. 第一次是由 URLClassLoader. 這發生在 CLTest
被 URLClassLoader load進來的時候. 因為你用了 new URLClassLoader(xx, null),
因此使得 URLClassLoader 沒有 parent classloader. 原本是 parent first
的 URLClassLoader 只能從 jar file 找 CLI2, 因此 project A 的 CLI2 被 load
進來給 CLTest 用. 如果不指定為 null, URLClassLoader 就會先從他的 parent
classloader AppClassLoader 找 CLI2, 也就會把 project B 的 CLI2 load 進來.
在 URLClassLoader 沒有 parent classloader 下, CLI2 第二次是由
AppClassLoader load 進來, 這發生在 CLI2 ci = (CLI2)o;
但是 CLTest所用的 CLI2 是由 URLClassLoader 來的, 因此發生不能 cast 的問題.
以上是我的猜想.
: 我的問題是,我要如何在Project B保有inteface CLI2的情況下
: 可以讓他跟我用URLClassLoade載入的CLTest物件相容
: 或是用Thread.currentThread().getContextClassLoader()
: 讓他可以抓到CLT2的interface部出現error
: 請高手指教
也就是說, 把 CLI2 弄成 public 就好了.
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 76.124.53.119
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 3 之 3 篇):