2012-03-16 3 views
0

JMX를 통해 Tomcat에서 실행중인 서블릿과 Tomcat의 동일한 인스턴스에서 실행중인 다른 서블릿을 모니터링하고 있습니다. 표준 Java 데이터 유형 (String, int, byte [] 등)을 반환하도록 get()을 설정하면 정상적으로 작동합니다.JMX를 통해 사용자 정의 클래스에 액세스 할 때 ClassCastException이 발생합니다.

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

나는이 때문에 계측에서와 관리 계층에서 다른 클래스 로더입니다 상당히 확신합니다 (: 나는 사용자 정의 클래스를 사용할 때, 나는이 메시지를 제공 ClassCastException를 얻을 서블릿을 모니터링하고 각각 모니터링 서블릿). 각 서블릿에 대한 사용자 정의 클래스가 들어있는 .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()을 생성 할 수 있지만 , 나는 하나의 호출로 데이터를 얻을 수 있도록 다시 보내려는 다양한 표준 비트와 bob (표준 Java 데이터 유형)을 모두 캡슐화하는 자체 POD/POJO 클래스를 작성/사용하고 싶습니다.

의견이 있으십니까? tomcat7, java6, 윈도우 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를로드 한 두 개 이상의 다른 클래스 로더가 있어야합니다.

라이프 사이클

하나의 클래스 로더가 있도록 getAllDataFromMBean를 정의하는 클래스가 같은 클래스 로더에 classloaded되어 있는지 확인합니다 :

은 몇 가지 옵션이 있습니다.(까다로울 수도 있음)

또는 클래스를 포함하는 jar 파일을로드하기 전에 시스템 클래스 경로에 넣으십시오. 당신의 getAllDataFromMBean 방법은 가능한 한 빨리 My_UserDefinedClass의 부하를 유발 한 것이다 클래스에 있기 때문에 (부트 클래스 경로 즉, 또는 시스템 클래스 경로)

반사

여기에 클래스 로더와 핵심 문제있다 이로드되었으므로 방망이 바로 옆에는 두 개의 다른 클래스 로더가 있으므로 호환되지 않는 유형이 있습니다. 따라서 기본 값은 모두 표준 Java 유형이므로 인스턴스를 반영하여 액세스 할 수 있습니다.

** 총칭 **

오히려 당신의 가치에 대한 사용자 정의 클래스를 만드는 것보다, 이름/값 맵에 보관하십시오. 그렇게하면 전달되는 모든 데이터가 핵심 Java 유형에 있습니다.

** 외적 **

당신이 (바이트 []에 말) 직렬화 할 수있는 사용자 정의 인스턴스를 강제하고 읽기 끝에 직렬화 경우

, 당신은이 문제를 우회 할 것이다.

** 개방형 ** **

이것이 해결책이라고 생각합니다. 유형을 CompositeData으로 정의하십시오. 그런 식으로, 사용자 정의 클래스 종속성은 전혀 없습니다. 이것은 클래스 패스에 커스텀 클래스조차 갖지 않는 원격 JMX 클라이언트 (JConsole과 같은)에 값을 표시 할 수 있다는 점과 같은 장점이있다.

// 니콜라스

+0

감사합니다, 이것이 답일 것 같았지만, 아아아, 나는 똑같은 결과를 얻었습니다. 표준 자바 클래스 만 전달할 수 있다는 JMX의이 명백한 한계에 정말 놀랐습니다. 이것이 내가 본 예제가 int와 Strings 만 * 사용자 정의 클래스가 아니며 JMX 컨텍스트에서 사용자 정의 클래스에 대한 토론이 없었던 이유라고 생각합니다. – joe7pak

+0

이 답변에 대한 또 다른 생각. 나는 MBeanServer가 아닌 모니터링 된 서블릿에서 클래스 로더가 필요하다고 생각한다. 문제는 모니터링되는 서블릿에 대한 참조를 모니터링 서블릿에 포함 시키려하지 않고 있다는 것입니다. 모니터링되는 각 서블릿에 대해 모니터링 서블릿을 편집 할 필요없이 모니터링 된 서블릿을 추가 할 수 있습니다. – joe7pak

+0

좋아요, 여기 우승자가 있다고 생각합니다. – joe7pak

관련 문제