簡體   English   中英

如何使用由不同的ClassLoader實例化的對象

[英]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的公共接口嗎?

我已經嘗試過幾件事,例如

  • MyApplet實現MyInterface,然后將其強制轉換為MyInterface
  • 將成員JarClassLoader.applet的類型更改為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM