2012-03-16 15 views
0

JMX経由で、Tomcatで実行されているサーブレットとTomcatの同じインスタンスで実行中の別のサーブレットを監視しています。標準のJavaデータ型(String、int、byte []など)を返すようにget()を設定すると、正常に動作します。私は、ユーザー定義のクラスを使用する場合でも、私はこのメッセージを与えるClassCastExceptionが取得:JMX経由でユーザー定義クラスにアクセスするときのClassCastException

java.lang.ClassCastException: blah.My_UserDefinedClass cannot be cast to blah.My_UserDefinedClass 

私は、これは計測で、経営層(であるため、異なるクラスローダであるかなり確信していますサーブレットとモニタリングサーブレットをそれぞれ監視します)。私は各サーブレットのユーザー定義クラスを含む.jarファイルを二重チェックし、両方のjarファイルは互いに同じものです。

私は標準MBeanを使用していて、この属性を返すために、監視対象のサーブレットを設定している:

public interface MyMonitorMBean 
{ 
    public My_UserDefinedClass getAllData(); 
} 

実装:このデータにアクセスするための管理サーブレットで

public class MyMonitor implements MyMonitorMBean 
{ 
    private My_UserDefinedClass mAllData; 

    @Override 
    public My_UserDefinedClass getAllData() 
    { 
     return mAllData; 
    } 
} 

コード:

private void getAllDataFromMBean() 
{ 
    try 
    { 
     // this line generates the ClassCastException 
     My_UserDefinedClass allData = (My_UserDefinedClass)mMBS.getAttribute(mObjectName, "AllData"); 
    } 
    catch(Exception e) 
    { 
    } 
} 

標準のJavaデータ型を送信するたびに複数のget()を生成できますが私は、標準のJavaデータ型であるさまざまな標準ビットとボブをすべてカプセル化して自分のPOD/POJOクラスを構築/使用したいと思います。

どのような考えですか? tomcat7、Java6の、Windows XPの、32ビットを使用して

おかげで、

ビル

+0

さて、ここでの可能な解決策があります:代わりにMBS.getAttributeを(呼び出す)、*全ての*その値を持つ属性を返す必要がありMBS.getAttributes()を呼び出します。 MBeanクラスを単純化することはできませんが、管理レイヤーではやや単純化できます。 – joe7pak

答えて

0

これはあなたのために働くことがあります。 [一時的に]スレッドのコンテキストクラスローダをMBeanのクラスローダに設定する必要があります。これは、MBeanServerからクラスローダーインスタンスを要求することで判断できます。

private void getAllDataFromMBean() 
{ 
    try 
    { 
     final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); 
     try { 
      ClassLoader mbeanClassLoader = mMBS.getClassLoaderFor(mObjectName); 
      Thread.currentThread().setContextClassLoader(mbeanClassLoader); 
      My_UserDefinedClass allData = (My_UserDefinedClass)mMBS.getAttribute(mObjectName, "AllData"); 
      // Process allData here 
     } finally { 
      Thread.currentThread().setContextClassLoader(originalClassLoader); 
     } 
    } 
    catch(Exception e) 
    { 
    } 
} 

==== ==== UPDATE

密接に関連する質問は、より包括ここで答えもあります:ClassCastException when casting to the same classを。

==== UPDATEは====私は正確にあなたが持っている設定が、一つの方法または他に完全に明確ではないです

、あなたは間違いなく、実行時に、クラスローダの問題を持っている、あなたは、 My_UserDefinedClassをロードした2つの異なるクラスローダーがあります。

これらは、いくつかのオプションがあります:

ライフサイクル

は、唯一のクラスローダがあるのでgetAllDataFromMBeanを定義するクラスが同じクラスローダにクラスロードされていることを確認してください。

また、クラスを含むjarをシステムクラスパスに入れてからロードすることもできます。あなたのgetAllDataFromMBean方法はできるだけ早くMy_UserDefinedClassの負荷を誘発してしまうクラスであるため(すなわち、ブートクラスパス、またはシステムクラスパス)

リフレクション

クラスローダで問題の核心はここにありますがロードされましたので、バットのすぐ下に2つの異なるクラスローダーがあり、互換性のないタイプがあります。したがって、基本となる値はすべて標準のJava型であるため、インスタンスに反射的にアクセスできます。むしろ自分の価値観のためのユーザー定義のクラスを作成するよりも

**総称化**

、名前/値のマップに保管してください。そうすれば、渡されるすべてのデータはコアJava型になります。

**外在**

あなたは連載([]バイトに言う)、次に読み終わりに、それをデシリアライズするために、ユーザ定義されたインスタンスを強制する場合は、この問題を回避します。

**オープンタイプ**

これは私が最善だと思うのソリューションです。タイプをCompositeDataと定義します。 このように、カスタムクラスの依存関係はまったくありません。これには、クラスパスにカスタムクラスを持たないリモートJMXクライアント(JConsoleなど)の値を表示できるという利点があります。

//ニコラス

+0

ありがとう、これは答えのように見えましたが、悲しいかな、私はまったく同じ結果を得ています。私は本当にJMXのこの明らかな制限によって、標準のJavaクラスだけが渡せることに驚いています。これは、私が見た例では、intとStrings、そして決してユーザー定義のクラスのみを示し、JMXコンテキストではユーザー定義のクラスについての議論は決して*なかったからです。 – joe7pak

+0

この回答についてもう一度考えました。私は、MBeanServerからではなく、監視対象のサーブレットからクラスローダーが必要だと思っています。問題は、監視対象サーブレットへの参照を監視サーブレットに含めないようにしようとしていることです。これは、監視対象のサーブレットごとに監視サーブレットを編集することなく、監視対象サーブレットを追加できるようにするためです。 – joe7pak

+0

さて、ここに勝者がいると思います。 – joe7pak

関連する問題