6

一般的に言えば、1 つのコード セット (クライアント コード) が別のコード セット (API コード) とリンクします。Java リンクは通常、コンパイル時に .java と .class の間、または実行時に .class と .class の間で検証されます。ただし、後者の場合、検証は不正な参照に遭遇したときと同じです (つまり、怠惰です)。

コンパイルされたコードを使用して、クライアント コードと API コードの間のすべてのリンクを一度に強制的に検証する方法はありますか? 目的は、クライアント コードが特定のバージョンの API で動作することを確認することです (別のバージョンに対してコンパイルされている場合でも)。

(もちろん、API に対して逆コンパイルして再コンパイルするのも 1 つの方法ですが、もっと直接的な方法はありますか?)

4

6 に答える 6

1

言語の性質と JVM の実装により、リンクの強制検証は困難です。

この質問の論理的根拠は、実行時のリンケージ エラーを防止することであり、そうする意図は非常に有効です。ただし、リンケージ エラーの原因を JVM の観点から見ると、パフォーマンスに影響を与えずに検証を強制的に実行することは多かれ少なかれ困難です。

JVM がメソッド呼び出し命令に対応するバイトコードを実行すると、実行時にリンケージ エラーがスローされます。通常、JVM のバイトコード ベリファイアの遅延最終パスが開始されるのはこの時点であり、リンク エラーが発生する可能性があります。言うまでもなく、これはパフォーマンスの観点から高価です。

(私の推測では) したがって、ほとんどのプロジェクト (商用のものを含む) は強制的な検証を避け、代わりにビルドと依存関係管理システムに依存して痛みを回避しています。この SO の質問に詳しい解説があります。OSGi フレームワークを選択するという答えが役立つかもしれません。

于 2010-07-28T19:30:28.237 に答える
0

再帰性によって Java クラスからコードを分析することが可能です。パッケージjava.reflectを参照してください。一部の分析ツールは、この機能を使用して、コンパイルされたコードに関する情報を取得します。最良の例は、おそらくFindBugsです。

この API は制限としてあり、それでやりたいことができるとは思いません。依存関係がメソッドで呼び出された場合、reflect API はメソッドとそのパラメーターを見つけることができますが、そのメソッドで使用される依存関数を提供することはできません。

そういう分析ツールはJavaには存在しないと思います。

解決策は、コードにすべての依存関係を一度提供することです。開発では、Maven などのライフサイクル管理ツールが、プロジェクトの依存関係を管理するのに役立ちます。

于 2010-07-28T18:58:14.680 に答える
0

必要に応じて、JarJarDiff[1] などのツールを使用して、API jar の新しいバージョンと古いバージョンの違いを取得できます。次に、タスクは、互換性のない API を使用していないことを確認することに変わります。自動ではありませんが、このアプローチは、バイナリ互換性だけでなく、変更点にも注意を向けます。

バイナリの互換性を確認するだけの場合は、新しい JAR に対してプロジェクトを再コンパイルするのが最も簡単です。クラスパスをスキャンし、各クラスの各メソッドを呼び出して、リンケージの例外を探すのは、もう少し難しい (そしてより脆い) 方法です。この素朴なアプローチは、考えられるすべてのパスをテストするわけではなく、メリットがほとんどないことに注意してください。

[1] http://depfind.sourceforge.net/tasks/jarjardiff.html

于 2010-08-04T14:52:42.613 に答える
0

この質問Alfresco Wikiからアイデアを得て-Xcomp、テスト JVM を開始し、クラスをプリコンパイルして、リンク エラーがあるかどうかを確認してみてください。

于 2010-08-09T12:09:52.137 に答える
0

おそらく、ClassPath の jar で指定された API に対して junit テストを実行してから、異なるバージョンの api 用に jar を切り替えて、テストを再度実行することができます。これを簡単に自動化できます。

于 2010-07-28T18:43:55.460 に答える
0

asm などのバイトコード ツールを使用してコードを「訪問」し、訪問者にvisitMethodInsnをオーバーライドさせることをお勧めします。次に、所有者クラスでリフレクションを使用して、示された名前とシグネチャを持つメソッドを探します。呼び出し命令のオペコードも確認する必要があります。これは、invokevirtual、invokeinterface、invokespecial、invokestatic のいずれかになります。invokevirtual と invokeinterface の違いに注意してください。invokevirtual を呼び出しても、インターフェイス メソッドは正常に呼び出されませんまた、invokeinterface を呼び出しても、インターフェイスで定義されていないメソッドは正常に呼び出されません。

于 2010-08-09T19:12:29.197 に答える