DLL自体を使用するのではなく、何らかのプラグインアーキテクチャが望まれているようです。
DLLを使用することをお勧めしない理由の1つは、Javaコードとネイティブコードをリンクするには、おそらく純粋なJavaソリューションよりも多くの労力が必要なJava Native Interface(JNI)を使用する必要があるということです。
比較的単純な方法の1つは、Javaのreflection機能を使用することです。
与えられた情報から、私はおそらく、次の線に沿って行くだろう:
- は、出力形式のインターフェイスを定義します。
- インターフェイスを実装するJavaクラスを作成します。
- クラスはclasspathから入手できます。
- リフレクションを使用して動的にクラスを読み込みます。 (
Class.newInstance
メソッドを使用すると、ClassLoader
によってロードclass
ファイルからオブジェクトをインスタンス化することができます。)これらのステップと
を、新しいフォーマットを完全に再構築する際のサポートを必要としない単純なプラグインを実装することが可能であろう必要とされている。
ステップ1:インターフェイスを定義し
のは、我々は次のようなインターフェースで終わるとしましょう:
public interface Outputter {
public void write(Data d);
}
ステップ2:実装クラスを作成します
次に、実装クラスを作成します。
public class TextOutputter {
public void write(Data d) {
// ... output data to text
}
}
次に、上記をコンパイルし、我々はTextOutputter.class
と呼ばれるclass
ファイルになってしまいます。
ステップ3:メインアプリケーションを実行している場合、クラスパス
からクラスを利用可能にするには、我々はclasspath上記TextOutputter.class
を持っている必要があります。通常は、JVMにクラスパスとして考慮する場所のリストを通知し、それには上記のclass
ファイルを含める必要があります。
これが完了したら、リフレクションを使用して上記のクラスを読み込むことができるはずです。
ステップ4:
// Note: We load the class by specifying the fully-qualified class name!
Class<?> clazz = Class.forName("TextOutputter");
// Then, we instantiate the class.
// Note that the following method will call the no-argument constructor.
Outputter outputter = clazz.newInstance();
// Now, we can give data to the TextOutputter object that we loaded dynamically.
outputter.write(...);
Class.forName
方法:動的に私たちが実際に上記のクラスをロードするとき、私たちは以下のような何かをしたい、今すぐ反射
を使用してクラスをロードクラスをデフォルトのClassLoader
から検索しようとします。クラスをClass
表現として取得すると、そのクラスのオブジェクトをインスタンス化できます。
オブジェクトをインスタンス化するには、Class.newInstance
メソッドを使用します。引数のないコンストラクタ以外を使用する必要がある場合は、そのクラスのConstructor
を取得してそこからオブジェクトをインスタンス化する必要があります。
オブジェクトは、リフレクションによってインスタンス化され、Outputter
変数に格納されるため、TextOutputter
でwrite
メソッドを呼び出すことができます。
上記のプロセスを追加すると、完全なクラス名(たとえばString
の場合はFQCNがjava.lang.String
の場合)を変更するだけで、別のクラスを読み込むことができます。一言で言えば
、それはそれは動的class
ファイルをロードし、アプリケーションからそれを使用するのにかかるものです。
(ただ、サイドノートとして、私は実際に上記のコードをコンパイルしていなかったので、ここにあるいくつかのエラーがあるかもしれませんが、私は、私はそれがかかりますプロセスを示してことを願っています。)
はい、JNIと動的ネイティブライブラリ(高性能または特定の外部ライブラリ用に、ラッパーとしてPOJOを使用する)を必要とするクラスを使用しない限り、これは機能します。 DLLクラスのクラスを標準クラスローダでリロードすることはできないので、その場合はサブクラス化する必要があります。 – dweeves
Javaの新しいバージョンでは、サービスプロバイダメカニズム(java.util.ServiceProvider)を使用して、プラグインjarからのプラグイン実装のロードを標準化することができます。 – jtahlborn
@dweeves:クラスローダーをサブクラス化する必要はありません。別のクラスローダーを使用して、dllをアンロードするときに破棄する必要があります。 – jtahlborn