4

私は最近、実行時にJavaコードを更新する投稿を作成し、数時間さまざまなサンプルコードをいじり、チュートリアルを読んだ後、次の問題に遭遇しました。

ClassLoader を使用することで、実行時にhttp://www.exampledepot.com/egs/java.lang/reloadclass.htmlMyVar1のコードを使用してローカル変数を ClassからClass に変更できましたが、置き換えることができませんでしたの別のバージョンを持つそのクラス。MyVar2MyVar2MyVar2

と インターフェイスの両方MyVar1MyVar2実装しますVarInterface。メイン クラスは、 type を使用して変数のインスタンスを保持しますVarInterface

正しいと主張する他のいくつかの実装を読みましたが、これを機能させることができません。ここで私が間違っていることを誰かが見ることができますか?

メインクラスのループ:

    while(true){  
        i++;  
        Thread.sleep(1000);  
        ui.ping();  
        if(i > 3)  
            replaceVar();  
    }

置換変数:

ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
    MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
    Class newClass = classLoader.loadClass("MyVar2");
    ui = (VarInterface)newClass.newInstance();

MyClassLoader.loadClass:

public Class<?> loadClass(String what){
    // Get the directory (URL) of the reloadable class
    URL[] urls = null;
    try {
        // Convert the file object to a URL
        File dir = new File(System.getProperty("user.dir")
                +File.separator+"dir"+File.separator);
        URL url = dir.toURL();
        urls = new URL[]{url};
    } catch (MalformedURLException e) {
    }

    // Create a new class loader with the directory
    ClassLoader cl = new URLClassLoader(urls);

    // Load in the class
    Class cls = null;
    try {
        cls = cl.loadClass("MyVar2");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

    return cls;
}

最初の 3 回の繰り返しMyVar1.ping()が呼び出され、その後はファイルとファイルMyVar2.ping()を置き換えても、無限に呼び出されます。MyVar2.classMyVar2.java

4

2 に答える 2

1

私は問題を解決することができました。クラスを別のバージョンに置き換えたときではなく、同じインターフェイスを実装する別のクラスの場合にのみ ClassLoader が新しいインスタンスを読み取るようにするクラスパスからファイルを保持するのを忘れていました。

つまり、基本的には、プロジェクトからファイルを削除して外部で編集することで問題が解決しました。

于 2010-06-21T10:40:29.230 に答える
1

2 つのクラスローダーを使用していると思います。1 つはシステム クラス ローダーで、大量のコードが含まれています。カスタム クラス ローダーは、システム クラス ローダーを親として使用します。カスタム クラス ローダーを取得して、システム クラス ローダーのクラスを置き換えようとしています。実際、カスタム クラス ローダーは、独自のクラスをロードするよりも親に委任します。

必要なことは、システム クラス ローダーがクラスの実装をロードしないことを確認することです。クラスの実装をロードし、システム クラス ローダーに委譲するクラス ローダーを作成します。実装を変更するには、クラス ローダーの別のインスタンスを作成します。

(java.net.URLClassLoader.newInstance独自のクラスローダー実装を作成する方がおそらく簡単です。)

于 2010-06-21T00:29:14.310 に答える