1

実行時に以前にロードされたクラスをリロードする必要があるアプリケーションを作成しています。その理由は、実行時にクラスが自動生成され、新しい実装によってアプリの動作が変わるためです。上記のクラスのオブジェクトを 1 つだけ生成し、定数値を定義するインターフェイス以外のすべての依存関係からそれを取り除きました。リロード時に一部またはすべてのメンバーの値をリセットしても問題はありません。それがいつ変化するかを正確に知っており、それを制御できます。私が抱えている唯一の問題は、リロード自体です。

私が読んだことから、ClassLoaderを使用する必要があります。そうしようとしましたが、うまくいきません。

私は次のことを試しました:

  • 現在の ClassLoader ( myClassObject.getClass().getClassLoader()) を取得し、それを使用してクラスをリロードする - 機能しません。おそらく古い実装をロードし続けます。
  • 独自の生成 (変更を加えた SO からの別名コピーアンドペースト) - 生成した ClassLoader がクラスを生成したものと異なるため、機能しません (例外: myClass は myClass にキャストできません)。
  • スーパークラスの ClassLoader を設定するコンストラクターを作成しても効果がないようです。
  • 新しい ClassLoader を使用して、メンバーとして myClassObject を持つクラスを生成すると、myClassObject の ClassLoader の不一致は解決されましたが、1 レベル上の新しい不一致が作成されました。私はgetClassLoader()いつも使っていましたが、それらが一致していないことがわかりました。
  • -Djava.system.class.loader=com.test.Reoader com.test.myMainClassデフォルトのリローダーにするために追加しようとしましたが、コンパイラからエラーが発生します。
  • グーグルは、私がすでに読んだものと同じものを私に指摘し続けます。
  • 編集:インターフェイスを作成して、それを実装するクラスをリロードしようとしました。それも解決しませんでした。

デフォルトの ClassLoader をオーバーライドする必要があることはわかっていますが、何も成功していないようです。

私のクラスローダー:

public class Reloader extends ClassLoader {

    public Reloader(){
        super(Reloader.class.getClassLoader());
    }

    @Override
    public Class<?> loadClass(String s) {
        return findClass(s);
    }

    @Override
    public Class<?> findClass(String s) {
        try {
            byte[] bytes = loadClassData(s);
            return defineClass(s, bytes, 0, bytes.length);
        } catch (IOException ioe) {
            try {
                return super.loadClass(s);
            } catch (ClassNotFoundException ignore) {}
            ioe.printStackTrace(java.lang.System.out);
            return null;
        }
    }

    private byte[] loadClassData(String className) throws IOException {
        File f = new File("out\\production\\ManoCPU\\" + className.replaceAll("\\.", "/") + ".class");
        int size = (int) f.length();
        byte buff[] = new byte[size];
        FileInputStream fis = new FileInputStream(f);
        DataInputStream dis = new DataInputStream(fis);
        dis.readFully(buff);
        dis.close();
        return buff;
    }
}

助けてくれる人に感謝します。

4

1 に答える 1

1

クラスをロードできるのは、(クラスローダーのインスタンスごとに) 1 回だけです。つまり、クラスをロードしたクラスローダーを破棄し、更新されたバージョンのクラス用に新しいクラスローダーをインスタンス化する必要があります。

複数のクラスローダーを扱う場合、複数のクラスローダーで同じクラスをロードすると、それらは同じクラスとして認識されないことにも注意してください。

于 2013-05-17T21:50:26.830 に答える