実行時に以前にロードされたクラスをリロードする必要があるアプリケーションを作成しています。その理由は、実行時にクラスが自動生成され、新しい実装によってアプリの動作が変わるためです。上記のクラスのオブジェクトを 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;
}
}
助けてくれる人に感謝します。