2

実行時にjarをロードするためのインターフェースを提供するプラグインシステムを開発しようとしています。各jarには、共通の抽象クラスから拡張されたクラスが含まれています。例えば:

//BasicPlugin.java
package byv;

abstract class BasicPlugin {
    abstract public int test(int a);
}

サブクラスを実装しました:

//PluginA.java
package byv;

import byv.BasicPlugin;

public class PluginA extends BasicPlugin {
    @Override
    public int test(int a) {
        return a + a;
    }
}

上記のサブクラスはコンパイルされ、jarファイル(PluginA.jar)にパッケージ化されました。このjarには、PluginA.classのみが含まれています。次に、メインプロジェクトで、URLClassLoaderを使用してロードします。

private static void loadTest() throws Exception {
    URL url = new File("PluginA.jar").toURI().toURL();
    URLClassLoader ClassLoader = URLClassLoader.newInstance(new URL[] {url});

    Class<?> clazz = Class.forName("byv.PluginA", true, ClassLoader);

    BasicPlugin obj = (BasicPlugin) clazz.newInstance();
    obj.test(2);
}

メインプロジェクトにBasicPluginへの参照をすでに追加しました。しかし、それでもエラーが発生しました。

Exception in thread "main" java.lang.IllegalAccessError: class byv.PluginA cannot access its superclass byv.BasicPlugin
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:277)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:212)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
    at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:615)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at byv.Main.loadTest1(Main.java:18)
    at byv.Main.main(Main.java:11)

では、どうすればこの問題を解決できますか?

4

2 に答える 2

1

それなので、問題を解決するために公開するIllegalAccessErrorことをお勧めします。BasicPlugin私の知る限り、あなたが定義したクラスはパッケージで保護されています。そのため、別のクラスローダーからはアクセスできません。これがプラグインに必要なものであるため、クラスをパブリック以外のものにすることは意味がありません。

もう1つURLClassLoaderは、親ローダーを指定できる2番目のコンストラクターがあります。次に、このローダーを使用してプラグインクラスをロードします。より複雑な環境では、そのローダーを指定することをお勧めします。現在、あなたのコードは多かれ少なかれシステムローダーを使用しています。これはあなたの例では問題ありませんが、後で何をするつもりかわかりません。BasicPlugin.class.getClassLoader()確かにそのクラスに適したローダーを提供します。

于 2012-05-22T08:09:40.160 に答える
1

URLClassLoaderインスタンスを構築するときに使用するクラスローダーコンテキストを渡します。

URLClassLoader ClassLoader = URLClassLoader.newInstance(new URL[] {url},
                                                        this.getClassLoader());
于 2012-05-22T08:10:49.427 に答える