18

私は現在、Java で書かれたプロジェクトを開発しています。私たちのプロジェクトに組み込む必要がある C/C++ で書かれた多数のアルゴリズム (少なくとも数百) があります。JNI を使用してこのコードを呼び出すか、すべてのアルゴリズムを Java で書き直すかの 2 つのオプションがあります。

JNI を使用すると、まったく新しい一連の問題が発生する可能性があることを認識しています。そのため、Java ですべてのコードを書き直すことさえ検討されています。しかし、それを書き直すという考えは...間違っているようです。アルゴリズムはテスト済みで、私の知る限り動作しますが、言語が間違っているだけです。

この状況で、JNI はこのタスクを容易にしますか? それとも、Java でコードを書き直すよりも頭痛の種になるのでしょうか?


編集 #1: 関連する質問 - JNI の有用性


編集 #2: 参考までに - 私たちの Java プロジェクトは、移植性を意図したものではありません。これにより、おそらく移植性が低下するという JNI の欠点の 1 つが解消される可能性があります。

4

11 に答える 11

18

簡単な答えは、コードが頻繁に呼び出され、パフォーマンスが問題になる場合は、それを Java に変換することです。

より複雑な答えは次のとおりです。

  • ライブラリが JNI で簡単にラップされている場合は、JNI を使用します
  • C/C++ コードのテストが簡単に Java に変換された場合は、移植に進みます。

私は次のことをします:

  • アルゴリズムの 1 つを取り、それを JNI でラップする
  • 同じアルゴリズムを Java に変換する
  • どちらを行うのがより苦痛であるかを確認してください
  • 速度が重要な場合は、両方のバージョンをプロファイリングして、どちらが許容できるかを確認してください。
于 2009-03-04T18:51:15.400 に答える
14

答えは、呼び出し元の Java コードと呼び出された C/C++ コードの間の結合の量と、書き換えに伴う労力のレベルにあると思います。C コードがいくつかの整数を取り、毛むくじゃらの計算を行い、別の int を返す場合。JNI を使用します。前後に複雑なことがたくさんあるが、アルゴリズムがかなり単純な場合は、それらを書き直してください。障害行は JNI 接続です。それが複雑になる場合は、書き換え用のアルゴリズム コードよりも多くの JNI インターフェイス コードを作成することになる可能性があります。

于 2009-03-04T16:22:52.887 に答える
13

「アルゴリズム」が適切にパッケージ化されている場合、JNI を使用して自動グルー コードを作成することは可能でしょうか? これにより、エラーのリスクが軽減され (何百もの個別のコンポーネントを手動で作成するのは危険に思えます)、追加するアルゴリズムの数に多かれ少なかれコストが依存しなくなります。

何百ものコンポーネントを書き直すのは非常に危険に思えますが、少なくとも最初に JNI をより詳細に調査することをお勧めします。

プロジェクトの残りの部分に関して、アルゴリズムにはどのような I/O 要件がありますか? それらがかなり疎結合されている場合、Java からサブプロセスとして呼び出され、stdio などを使用してデータを共有する独立した個別のプログラムとして実行することは可能でしょうか?

于 2009-03-04T16:22:03.543 に答える
9

JNI を使用することは、飛び込む前に思ったほど困難ではないことがわかると思います。いくつかの重要なトレードオフと制限がありますが、一般的に JNI はうまく機能し、意図したとおりに活用するのはかなり簡単です。

他の人が言っているように、JNIの最良のケースは次のとおりです。

  • 複雑なネイティブ コード (そのコードが非常に信頼できることが既に証明されている場合はボーナス ポイント)
  • Java とネイティブ コード間の最小限のやり取り (JNI レイヤー全体の移動を最小限に抑えたい場合)
  • ネイティブ コードへのかなり単純な呼び出しインターフェイス (または、ネイティブ コードで Java オブジェクト/メソッドを利用する必要がある場合は、Java に戻る)

適切に構造化された一連のネイティブ コンポーネントの JNI レイヤーの作成を自動化または疑似自動化することは間違いなく可能です。ラップするコンポーネントの数が多い場合は、それだけの価値があります。

JNI の良いニュースは、このインターフェイスを簡単に構築してテストできることです。たとえば、既存のアルゴリズムの動作を利用する Java からテスト ケースを記述できる必要があります。アルゴリズムではなく、それ自体をレイヤー化します (ネイティブ実装に自信がある場合)。

Java で多数の C/C++ アルゴリズムを書き直すことは、JNI を使用するよりもはるかに危険に思えます。もちろん、詳細を知らなければ正確に判断するのは困難ですが、エンジニアリングの労力とエラーのリスクは言うまでもなく、アルゴリズムの実際の実装に影響を与えると想像できるテクノロジー間には微妙な違いがあります。

最後の考慮事項は、これらのアルゴリズムまたは関連コンポーネントの将来の寿命です。アルゴリズムのセットはほぼ完成していますか、それとも追加を続けていますか? いずれにせよ、ある技術を他の技術よりも優先する強力なメンテナンスおよび/または将来の開発理由はありますか? たとえば、他のすべてが Java であり、すべての新しいアルゴリズムが Java であり、チームのほぼ全員がほぼ常に Java でコーディングしている場合、Java での再実装は長期的にはより魅力的に見え始めます。

ただし、そうは言っても、作業は一貫性に勝ります。適切に機能する多数のネイティブ コンポーネントについては、長期的に Java に移行する予定がある場合でも、JNI から始める傾向があります。

于 2009-03-04T22:36:25.033 に答える
8

特に言語間インターフェースの数を最小限に抑えることができる場合は特に、JNI を使用することを真剣に検討します。

たとえば、すべて同じ入力と出力を持ち、入力に対して異なる処理を行う C 関数のスタック全体がある場合、使用する特定のアルゴリズムを指定する追加パラメーターを使用して単一の JNI ラッパーにラップします。

于 2009-03-04T16:23:29.640 に答える
8

C/C++ ではなく、Java で将来のプロジェクトを作成する予定がある場合。私は今、弾丸をかみ砕いて、コードを Java に移植します。待てば待つほど悪化します。この場合、JNI は魅力的に思えますが、そうすると、他の全員が楽しい新しい Java プロジェクトに取り組んでいるときに、誰かが C++ コードを保守しなければならないという問題が生じます。

これが 1 回限りの Java プロジェクトである場合、なぜ Java で記述しているのですか?

于 2009-03-04T16:23:48.407 に答える
3

C と Java の間のブリッジはコストがかかるため、大量のデータをやり取りする必要がある場合は、JNI を介して C を呼び出すことに勝るものはありません。

私は、リフレクションのような方法で Java から DLL/共有ライブラリのメソッドを呼び出す手間がはるかに少ない、JNI の合理的な代替手段として JNA がリストされているのを見てきました。まだ試していません。

Java で解釈できる Linux MIPS バイナリとして C コードをコンパイルすることを検討してください。かなり高速ですが、正しくセットアップするのは少し難しいです。http://nestedvm.ibex.org/を参照してください。

また、llvm バックエンドを gcc に使用して、Java で解釈できる低レベルのバイトコードにコンパイルすることもできます。これは、Mac OS X の iPhone SDK afaik で採用されたアプローチでもあります。 http://llvm.org/

于 2009-03-04T19:09:20.053 に答える
2

私はこの状況に陥っています。Java で利用できるマルチスレッド データ構造の使用に慣れることをお勧めします。この時点で、C++ データ構造に戻る必要はなくなります。

また、より思慮深い手法、より優れたポリモーフィズム、アダプター パターンなどを使用して、これらのアルゴリズムをより適切に書き直すことができることにも気付くでしょう。

C/C++ コードに座っているとき、あなたはそれに固執したいと考えています。あなたはそれに注いだすべての愛について考えています。数年後には、それを保持し、JNI を使用することで、怪物を作成したことに気付くでしょう。プロセスがクラッシュするたびに、JNI を使用したことを後悔するでしょう。プロセスのクラッシュを修正した後、誰かが C++ でアルゴリズムを変更したいと思うようになり、あなたはそれらを抑制したいと思うでしょう。「私はまだ Java に慣れていません」などの都合の良い言い訳をします。

Java の不変データ構造を見てみましょう。これらの古い C/C++ アルゴリズムの実行速度については考えないでください。新しいコードは、古い C/C++ コードよりもはるかに優れていることがわかりました。

単体テストを書きます。NetBeans を使用します。

敬具、

-ストッシュ

于 2009-04-21T01:50:58.227 に答える
2

「技術的負債の支払い」に関するジョエルの最近の投稿を読んでから、今後数年間にわたって利息を支払ってから返済するのではなく、今すぐ変換してください。

おそらく、再パッケージ化されたライブラリは、より多くの場所で役立つ可能性があります。それらが便利で複雑で、C に残しておくことを検討するほど十分である場合、再利用可能で配布が容易で理解しやすいクラスにうまくパッケージ化されると、さらに多くの用途があるはずです。

于 2009-03-04T17:51:47.540 に答える
1

JNIを試してみてください。次に、問題に直面した場合は、問題のあるものを書き直すか、JNI 呼び出しを Web サービスでラップして、別のボックスまたは仮想ボックスにデプロイします。

于 2009-03-04T16:23:33.727 に答える