8

Java1.5で絶対に実行する必要のあるコードをパッケージ化したい。VMが1.6VMの場合、プログラムを「拡張」できるコードの一部があります。

基本的にはこの方法です:

 private long[] findDeadlockedThreads() {
    // JDK 1.5 only supports the findMonitorDeadlockedThreads()
    // method, so you need to comment out the following three lines
    if (mbean.isSynchronizerUsageSupported())
      return mbean.findDeadlockedThreads();
    else
      return mbean.findMonitorDeadlockedThreads();
  }

これを1.5でコンパイルし、1.6で1.6メソッド呼び出しを行う最も簡単な方法は何でしょうか。

過去に、アプリと一緒にパッケージ化し、1.6のときにClassLoaderを使用してインスタンス化する一意の1.6クラスをコンパイルすることで同様のことを行いました(1.6 JVMは0x32クラスと0x31クラスを完全にうまく混合できるため)が、これは少しやり過ぎです(ビルドプロセス中に0x31と0x32の両方の.classファイルをビルドする必要があるため少し苦痛です)。

上記のメソッドを1.5でコンパイルしたい場合は、どうすればよいですか?たぶんリフレクションを使用しますが、どのように(私はリフレクションにまったく精通していません)

注:興味がある場合は、上記の方法は次の記事からのものです:http ://www.javaspecialists.eu/archive/Issue130.html

(ただし、記事のように「3行にコメント」したくないので、これをコンパイルして1.5と1.6の両方で実行したい)

4

3 に答える 3

3

これを1.5でコンパイルすることはできませんが、target-optionを1.5に設定して(1.5のバイトコードを生成する)1.6でコンパイルし、リフレクションを使用してコードでメソッドが使用可能かどうかを確認できます。

このコードはメソッドを検索します:mbean.getClass()。getMethod( "findDeadlockedThreads"、new Class [0]); 問題は、メソッドが存在しない場合、単にnullまたは同様のものを返す代わりに、NoSuchMethodExceptionをスローすることです。つまり、次のようなコードが必要です。

try
{
  mbean.getClass().getMethod("findDeadlockedThreads", new Class<?>[0]);
  return mbean.findDeadlockedThreads();
}
catch(NoSuchMethodException ex)
{
  return mbean.findMonitorDeadlockedThreads();
}

例外を使用して決定を下すため、これはあまり良いことではありません。それはおそらくそれほど速くはありません。別の方法は、代わりにgetMethodsを使用し、メソッドが使用可能な場合は返されたリストを反復処理することです。それもそれほど速くはありません。

編集: Christopher Oezbekはコメントで、メソッドの存在を1回だけチェックし、結果を保存してTry-catch-blockのオーバーヘッドを回避することを提案しています。そうです、良い解決策です。matt bは、使用されるクラスとメソッドがJava 1.5で使用可能かどうかを、Javaコンパイラのtarget-optionがチェックしないことを警告します。そうです(1.6メソッドに対してコンパイルしたいので、そうでなければ機能しません)。つまり、この問題を回避するには、プログラムを1.5VMで慎重にテストする必要があります。ふたりのコメントありがとうございます。

于 2010-03-15T16:16:00.203 に答える
2

1.5用にコンパイルします。

コードではリフレクションを使用します。クラスインターフェイスからメソッドオブジェクトを取得できます。mbeanインスタンスをパラメータとして受け取るinvokeメソッドがあります。このようなもの:

クラスc=mbean.getClass(); //YourClass.classを実行してこれを取得することもできます

メソッドm=c.getMethod( "findMonitorDeadLockedThreads"); //またはその他のメソッド(メソッドのパラメーターはClassで指定されます... getMethodの2番目のパラメーター)

m.invoke(mbean)//インスタンスでメソッドを呼び出します

もちろん、毎回これを行う必要はありません。コンストラクターでメソッド参照をセットアップしてから、オンデマンドで適切なメソッド参照を呼び出すだけです。

于 2010-03-15T16:17:59.040 に答える
1

Mavenを使用すると、プロファイルを使用してこれを非常に簡単に行うことができます。プロファイルの背後にある考え方は、いくつかの基準に基づいて、何かの2つの異なるバージョンを構築したいということです。jdk15この特定の例では、とプロファイルを定義し、jdk16それぞれをコンパイルするJDKバージョンを指定して、クラスの1つのコピーをjdk15プロファイルに、もう1つをjdk16に含めるように指示できます。

開始するには、以下を参照してください。

http://unserializableone.blogspot.com/2008/09/compile-and-test-with-different-jdk.html

これは、問題のさまざまなJDKバージョン部分を実行する方法を説明しています。

JDKのバージョンに応じてクラスの異なる定義を使用して、問題の2番目の部分を処理するには、次を参照してください。

Maven-ビルド時にさまざまなファイルを含める

于 2010-03-15T16:18:20.303 に答える