[英]How to use an object instantiated by a different ClassLoader
我的小程序需要的類是外部jar(帶符號的jar)和本機庫的一部分。 我將這些jar部署在applet.jar中。 要從這些jar中加載類,我發現com.jdotsoft.jarloader.JarClassLoader類很有用。 我首先構建一個控制台應用程序來測試我的applet的功能,並且JarClassLoader對我來說工作正常。 接下來,我用另外兩個公共方法編寫了MyApplet類,比方說action1()和action2()。 並且,如JarClassLoader所述,我編寫了一個MyAppletLauncher類。 (請參見下面的代碼)。 為了獲得對MyApplet對象的引用(由JarClassLoader實例化),我將getApplet()方法添加到JarClassLoader類中。
MyApplet.java:
public class MyApplet extends Applet {
public void init() { ... }
public void start() { ... }
public void stop() { ... }
public void destroy() { ... }
public String action1() {
...
}
public int action2() {
...
}
}
MyAppletLauncher.java:
public class MyAppletLauncher extends Applet {
private JarClassLoader jcl;
public void init() {
jcl = new JarClassLoader();
jcl.initApple("MyApplet", this);
}
public void start() {
jcl.startApplet();
}
public void stop() {
jcl.stopApplet();
}
public void destroy() {
jcl.destroyApplet();
}
public String action1() {
return ((MyApplet) jcl.getApplet()).action1(); // <-- ClassCastException
}
public int action2() {
return ((MyApplet) jcl.getApplet()).action2(); // <-- ClassCastException
}
}
我對JarClassLoader.java的更改:
public class JarClassLoader extends ClassLoader {
private Applet applet; // was JApplet
public JarClassLoader() {
this(ClassLoader.getSystemClassLoader());
}
public JarClassLoader(ClassLoader parent) {
super(parent);
...
}
public void initApplet(String sClass, final Applet appletParent) { // 2nd arg was JApplet
Class<?> clazz = loadClass(sClass);
applet = (Applet) clazz.newInstance();
...
}
public Applet getApplet() {
return applet;
}
...
在我看來,很明顯MyAppletLauncher實例無法將提供的Applet實例向下轉換為MyApplet,因為MyApplet實例是在不同的命名空間中創建的(=不是由同一類加載器創建的)。 但是,我的問題是如何獲得對MyApplet對象的action1()和action2()調用? 或更常見的是,我可以從MyAppletLauncher對象調用MyApplet的公共接口嗎?
我已經嘗試過幾件事,例如
但是所有這些都會在某個時刻導致ClassCastException。
任何建議都歡迎。 謝謝。
我認為您缺少啟動程序小程序的要點。 一方面,它充當小程序容器與其系統ClassLoader之間的墊片,另一方面,它充當JCL加載的真實小程序和JCL。 除了applet生命周期方法外,啟動器applet中應該沒有任何內容。
我不確定如何在啟動程序applet上調用除生命周期方法以外的任何方法。 那不是偶然的,所以就別再嘗試了。 在真正的applet類和所需的任何幫助程序類中實現您applet的所有功能,就像啟動器applet不存在一樣。
如果必須讓外部組件在其applet上查找並調用方法,則使用與應用程序生命周期方法相同的模型,修改或子類化JCL以提供其他的shim方法。
我們看不到代碼的那部分,但是如果您的JarClassLoader
正確地鏈接到父類加載器(它可能沒有),那么接口解決方案應該可以工作。 前提是該接口是由主類加載器而不是自定義外部jar加載的。
您需要做的是這樣的:
public void init() {
jcl = new JarClassLoader(this.getClass().getClassLoader());
jcl.initApplet("MyApplet", this);
}
而且JarClassLoader
應該調用ClassLoader
的適當的超級構造函數 。 這樣,可以由“主”類加載器加載的任何類將僅加載一次,因此強制轉換為接口。
更新:如果JarClassLoader
的非委托行為,那么您的下一個最佳選擇是反射。 這不是很好,但至少可以正常工作。
public void action1() {
Applet applet = jcl.getApplet();
Method action = applet.getClass().getDeclaredMethod( "action1" );
action.invoke( applet );
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.