作者Maisky (McDummy)
看板java
标题Re: [问题] ClassLoader的一个问题[已解决]
时间Wed Dec 16 10:44:25 2009
※ 引述《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