2

私たちのアプリケーションは、JVisualVM を使用して呼び出す JMX を介していくつかのメソッドを公開します。

これは正常に機能しますが、アプリケーション内で例外が発生してメソッド呼び出しが中止されることがあります。その場合、例外からのエラー メッセージを表示する代わりに、JVisualVM はエラー メッセージを表示します。

java.rmi.UnmarshalException [...] error unmarshaling return; 
nested exception is: java.lang.ClassNotFoundException [...]

これは役に立たず、混乱を招きます。JVisualVM に実際のエラー メッセージを表示してもらいたいのです。

これまでにわかったこと:

JMX は、呼び出し中にスローされた例外をシリアライズおよびデシリアライズするようです。ただし、この場合、例外は JDK の一部ではないカスタム例外です。したがって、JVisualVM を介してメソッドを呼び出すと、未知のカスタム例外クラスが原因で逆シリアル化が失敗するため、JVisualVM は例外を表示できません。

現在、回避策として、JMX を介して公開されているすべてのメソッドをtry-catchブロックでラップしています。

    throw new RuntimeException("Error invoking method:"+e);

これは例外を文字列に変換するため機能しますが、かなり洗練されておらず冗長に見えます。

  • 例外をシリアル化しないように JMX に指示する一般的な方法はありますか? 「常に例外を文字列に変換する」のようなものですか?
  • Spring のMBeanExporterを使用します。これを処理するSpringのメカニズムはありますか?

編集

問題のクラスをロードするように JVisualVM を構成できることがわかっています。ただし、特別な構成なしで JVisualVM を動作させたいと考えています。また、アプリケーション コードが利用できないシステムを実行する場合もあります。

4

2 に答える 2

1

java.io.Serializableを見てください。カスタム例外に配置できるwriteReplaceというオプションのメソッドを実装できます。元のメッセージで一般的な例外を返します。例外がシリアル化されると、ジェネリックが送信されます。または、文字列を送信することもできますが、それがVisualVMでうまく機能するかどうかはわかりません。データチェックの厳しさにもよると思います。

オブジェクトをストリームに書き込むときに使用される代替オブジェクトを指定する必要があるシリアル化可能なクラスは、正確な署名を使用してこの特別なメソッドを実装する必要があります。

ANY-ACCESS-MODIFIERオブジェクトwriteReplace()はObjectStreamExceptionをスローします。

=====更新=====

とった。サードパーティライブラリ....要約....ここでの課題は、setAttribute [s]呼び出してJVisualVMを介してMBeanを呼び出すと、JVisualVMのクラスパスで使用できないタイプの例外がスローされることです。

MBeanServerにある種のインターセプターを実装すると、スローされた例外(おそらく、java またはjavax。で始まらないクラス名の例外)をトラップし、元の例外を表す非常に豊富なエラーメッセージを含むRuntimeExceptionsとして再スローする可能性があります。 。(有用な場合は、スタックトレースの文字列レンダリングを含めることもできます)。これは、1つの場所に集中化され、クラスの実装方法に依存しないという利点があることを除いて、基本的に現在行っていることです。

MBeanServerインターセプターは標準のJMX仕様にはまだ含まれていませんが、実際のMBeanServerに委任するだけの独自のMBeanServer実装を作成することでそれらを模倣できますが、setAttribute [s]およびinvoke呼び出しの場合は、「catch-and-再スロー」テクニック。大手術のように聞こえるかもしれませんが、複雑なアプリケーションサーバーのJMX実装に関する厄介な問題は別として、実際にはかなり簡単です。

例については、このstackoverflowの投稿とこの要点を参照してください。

.....とはいえ、Springを使用しており、MBeanが登録されている正確なMBeanServerインスタンスと、JVisualVMによって使用されているJMXConnectorServerに公開されているMBeanServerを指定できます。したがって、次の方が簡単です。

  1. 要旨で概説されているMBeanServerラッパーのアイデアを使用し、Springで構築して、実際のMBeanServerをデリゲートとして注入します。
  2. SpringJMXエクスポーターでラッパーBeanを参照します。
  3. JMXConnectorServerでラッパーBeanを参照します。

自動的にブートストラップするデフォルトのJMXConnectorServerを使用している場合は、 Springで定義されたものを使用するように切り替える必要があります。

Springベースのアプローチには、リモートMBeanServer呼び出し(JVisualVM呼び出しなど)のみが例外の書き換えを経験するという追加の利点がありますが、アプリケーションの内部呼び出しは、実際のMBeanServerに直接アクセスできるため、実際の例外を取得します。

=====もう1つの更新=====

Spring JMXサポートには、実際にはMBeanインターセプターの実装があります。私はそれについて知りませんでしたが、この問題について考えていたとき、Springが実装するもののように聞こえました、そしてそこにあります.....

于 2012-04-20T21:47:59.197 に答える
1

-Djava.rmi.server.codebaseリモート JVM から例外クラスをロードできるように、JVisualVM で試してみることはできますか?

編集:それをしたくない場合は、アスペクトを使用してtry-catchブロックと同等のことを行うことができます。そうすれば、必要なのは 1 か所だけです。すでにSpringを使用している場合、Spring AOPはそれを非常に簡単にします。

于 2012-04-20T09:49:10.857 に答える