2011-01-05 4 views
3

私は現在、いくつかのカスタムフォーマットで出力したいデータセットを持っているJavaプロジェクトに取り組んでいます。私は生データを受け取りそれに応じて変換する各形式のクラスを持っています。しかし、まず2つまたは3つのフォーマットを実装するだけですが、後でアプリケーションの大規模な再構築をせずにさらに多くのフォーマットを追加できるようにしたいと考えています。動的JavaプログラムのDLL?

私の考えは、各形式クラスのDLLを作成し、それぞれのアプリケーションに変換するデータを渡すようにしました。この方法で、私は後でDLLを作成し、メインアプリケーションにアクセスさせてもらうことができます。 (私は喜んでこれを行う代わりの方法を聞いていますが、C++/C#でこれをやった人は論理的な解決策だと感じましたが、Javaには当てはまらないかもしれません)

私の問題は、どのようにこれを行うかわからない - C + +/C#で私はコードのいくつかの行でこれを書くことができますが、私はどのようにJavaで動作するか分からない。ひどく曖昧な質問をする危険性がありますが、どうしたらいいですか?

回答は非常に高く評価され、クッキーと紅茶が提供されます。 :)事前に

おかげで、 M

編集:申し訳ありませんが、ちょうど追加する:私はこのプロジェクトのためにJavaでなければなりませんDLLを作成する方法もわからないAMは、最初の場所で読み取られます。ありがとう。 :)あなたはJavaで使用する(DLLにコンパイル)ネイティブコードを書きたい場合は

答えて

5

DLL自体を使用するのではなく、何らかのプラグインアーキテクチャが望まれているようです。

DLLを使用することをお勧めしない理由の1つは、Javaコードとネイティブコードをリンクするには、おそらく純粋なJavaソリューションよりも多くの労力が必要なJava Native Interface(JNI)を使用する必要があるということです。

比較的単純な方法の1つは、Javaのreflection機能を使用することです。

与えられた情報から、私はおそらく、次の線に沿って行くだろう:

  1. は、出力形式のインターフェイスを定義します。
  2. インターフェイスを実装するJavaクラスを作成します。
  3. クラスはclasspathから入手できます。
  4. リフレクションを使用して動的にクラスを読み込みます。 (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変数に格納されるため、TextOutputterwriteメソッドを呼び出すことができます。

上記のプロセスを追加すると、完全なクラス名(たとえばStringの場合はFQCNがjava.lang.Stringの場合)を変更するだけで、別のクラスを読み込むことができます。一言で言えば


、それはそれは動的classファイルをロードし、アプリケーションからそれを使用するのにかかるものです。

(ただ、サイドノートとして、私は実際に上記のコードをコンパイルしていなかったので、ここにあるいくつかのエラーがあるかもしれませんが、私は、私はそれがかかりますプロセスを示してことを願っています。)

+0

はい、JNIと動的ネイティブライブラリ(高性能または特定の外部ライブラリ用に、ラッパーとしてPOJOを使用する)を必要とするクラスを使用しない限り、これは機能します。 DLLクラスのクラスを標準クラスローダでリロードすることはできないので、その場合はサブクラス化する必要があります。 – dweeves

+0

Javaの新しいバージョンでは、サービスプロバイダメカニズム(java.util.ServiceProvider)を使用して、プラグインjarからのプラグイン実装のロードを標準化することができます。 – jtahlborn

+0

@dweeves:クラスローダーをサブクラス化する必要はありません。別のクラスローダーを使用して、dllをアンロードするときに破棄する必要があります。 – jtahlborn

1

は、あなたがJava Native Interface (JNI)を見てみたいです。あなたはJavaでライブラリ(DLL)をロードするためにSystem.loadLibrary(String libName)(ライブラリー名を知っているし、ライブラリパスが設定されている場合)またはSystem.load(String filename)(ライブラリファイル名)を使用することができます

を更新。

1

System.loadLibrary()を使用して、いつでも新しいDLLをロードできます。ただし、バインドするためにJavaクラスをロードする必要があります。

これは(共有ライブラリを含む)モジュールのロードとアンロードの両方をサポートしているとして、あなたは役に立つのOSGiコンテナを使用して見つけるかもしれない

私はiPOJOでkaraf使用することをお勧めだろうが、他の多くのがあります。

2

私はこのようなことをしました。 私はオープンなJavaベースのプラグインアーキテクチャーPOJOベースを作成しました。それは更新されたプラグインクラスの飛行でもリロードしました。 JNIは、ネイティブコードを処理するためのインターフェイスです。 唯一の技術的な部分は、DLLの再ロードを実行時に動的に有効にしたクラスローダーを書き直すことでした。 "オフライン"アップデートのみを行う場合、そのようなことは必要ありません。

1

私はあなたを考えますJNIパスを無視できます。私はあなたがより良い言葉の不足のために用語dllを使用しているという印象を持っています、あなたは本当にdllを必要としません。

Javaでも同じことができますが、フィルタはdllではなくjarファイルに入れます。

  1. フォルダを反復、アプリ内の1つの時点で(「フィルタ」のような)特定のフォルダ
  2. で、瓶にそれぞれ実装を入れ
  3. を実装するためのファイルフォーマットフィルタのインターフェイスを定義、彼らの仕事をするために、あなたのインターフェイスのすべての実装を見つけるために、瓶のため
  4. 使用反射をクラスローダを生成し、各
  5. コールするメソッドをクラスを作成

それは基本的にそれです。

1

のJava SE 6 ServiceLoaderクラスが導入されています ​​

あなたが適切なモジュラーアプローチをしたい場合はNetBeansプラットフォーム(それはデスクトップアプリケーションである場合は特に)、またはOSGiのを検討してください。

関連する問題