5

まず第一に、これはJava 1.4(プロジェクトの制限)です。アプリケーションマネージャーを作成しようとしています。カスタムクラスローダーの独自のインスタンスを使用して、各アプリケーションのメインクラスをロードします。その後、リフレクションを使用してメインクラスのインスタンスを作成します。各アプリケーションは共通のインターフェースを実装しているため、インスタンスが作成された後、アプリケーションの事前定義されたメソッドを実行します。

しかし、クラッシュポイント1で問題が発生しています(コードを参照)。このクラスは、そのインターフェースの1つの実装として認識されません。このコードチャンクをコメントすると、クラッシュポイント2でClassCastExceptionが発生します。

両方のエラーが同じ問題に関連していると思います(もちろん)。

誰か助けてもらえますか?コードの関連部分は次のとおりです(インポートは削除されます)...

どうもありがとう。

マーカス

// AppManager.java

public class AppManager {
    public ThreadGroup threadGroup;
    private Class appClass;
    private AppInstance appInst;
    public AppContextImpl context;

    private AppManager(CustomClassLoader cl, String mainClass) throws ClassNotFoundException {
        final String className = mainClass;
        final CustomClassLoader finalLoader = cl;

        appClass = cl.loadClass(mainClass);

        // DEBUG CODE:
        Class[] k1 = AppInstance.class.getInterfaces();
        System.out.println(k1.length + " interfaces for AppInstance.class:");
        for (int ii = 0; ii < k1.length; ii++) {
            System.out.println("   " + ii + " - " + k1[ii].getName() + " (" + k1[ii].getClassLoader() + ")");
        }

        Class[] k2 = appClass.getInterfaces();
        System.out.println(k2.length + " interfaces for appClass instance:");
        for (int ii = 0; ii < k2.length; ii++) {
            System.out.println("   " + ii + " - " + k2[ii].getName() + " (" + k2[ii].getClassLoader() + ")");
        }

        // CRASH POINT 1
        if (!(AppInstance.class.isAssignableFrom(appClass))) {
            throw new IllegalArgumentException("Attempt to run a non-AppInstance class: " + appClass);
        }

        context = new AppContextImpl(mainClass, this);
        cl.setAppManager(this);
        Constructor m;
        try {
            m = appClass.getConstructor(new Class[0]);
           // CRASH POINT 2
            appInst = (AppInstance) m.newInstance(new Object[0]);
            appInst.init(context);
        } catch (Exception e) {
            System.out.println("Got ClassCastException here!\n");
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        App app1;

        String path1 = "/home/user/workspace/MultiTaskTest/bin/";
        String app1Name = "App1";

        Vector v1 = new Vector();
        try {
            v1.add(new URL(path1));
        } catch (MalformedURLException e1) {
            final File file1 = new File(path1);
            try {
                URL path1aux = (URL) AccessController.doPrivileged(
                    new PrivilegedExceptionAction() {
                        public Object run() throws IOException {
                            if (!file1.exists()) {
                                System.out.println("Warning: \"" + file1.getPath() + "\" not found");
                                return null;
                            }
                        return file1.toURI().toURL();
                        }
                    });

                if (path1aux != null) {
                    v1.add(path1aux);
                }
            } catch (PrivilegedActionException e) {
                e.getException().printStackTrace();
            }
    }

        final URL[] array1 = (URL[]) v1.toArray(new URL[v1.size()]);
        CustomClassLoader cl1 = (CustomClassLoader) AccessController.doPrivileged(
            new PrivilegedAction() { public Object run() {
                return new CustomClassLoader(array1);
            }});
        System.out.println("ClassLoader 1 created: " + cl1);
        try {
            app1 = new App(cl1, app1Name);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("Cannot find class App1.");
        }
    }
}

// AppInstance.java

public interface AppInstance {
    public void init(ContextImpl context);
}

// App1.java

public class App1 implements AppInstance {
    private AppContextImpl contextObj;

    public void init(AppContextImpl context) {
        this.contextObj = context;
        System.out.println("Running App1...");
    }
}

// AppContextImpl.java

public class AppContextImpl {
    public String mainClass;
    public AppManager app;

    public AppContextImpl(String mainClass, AppManager app) {
        this.mainClass = mainClass;
        this.app = app;
    }
}

// CustomClassLoader.java

public class CustomClassLoader extends URLClassLoader {
    AppManager appInst;

    public CustomClassLoader(URL[] paths) { super(paths, null); }
    public void setAppManager(AppManager app) { this.appInst = app; }
}

AppManager.javaファイルのデバッグコードの出力は次のとおりです。

0 interfaces for AppInstance.class:
1 interfaces for appClass instance:
   0 - AppInstance (CustomClassLoader@480457)
4

1 に答える 1

4

AppInstance クラスは、おそらく各カスタム クラスローダーによって個別にロードされます。クラスオブジェクトは実際のクラスとクラスローダーに依存するため、実際には異なるクラスです。したがって、クラスローダー 1 の AppInstance は、クラスローダー 2 の AppInstance と同じではありません。

必要なことは、標準のクラスローダー階層を使用することです。アプリケーションにルート クラスローダーを使用し、AppInstance がクラスローダーによってロード可能であることを確認してください。次に、ルートからカスタム クラスローダーの子を作成します。AppInstance クラスにアクセスする必要があるときはいつでも、ルートからロードされたものを使用します。

したがって、これの代わりに:

public CustomClassLoader(URL[] paths) { super(paths, null); }

CustomClassLoader に親を与える必要があります

于 2010-06-08T17:52:52.203 に答える