2011-08-16 4 views
6

동일한 클래스를로드하는 ClassLoader가 두 개 있습니다. 그래서 분명히 이들은 서로에게 던져 넣을 수 없습니다. 하지만 다른 ClassLoader에서 생성 된 객체에 액세스해야합니다.ClassLoader 문제로 인한 ClassCastException 솔루션

클래스 로더에 액세스 할 수 있습니다. 다른 클래스의 객체를 어떻게 사용할 수 있습니까? 현재 ClassLoader와 일치하도록 객체를 캐스팅 할 필요가 없습니다.

하지만 문제는 반환 된 개체의 형식이 Object입니다. 그래서, 나는 몇몇 객체에 접근하기 위해 객체를 캐스팅해야합니다. 어떻게해야합니까? 다음과 같은 일반적인 캐스트는 이미 알고있는 ClassCastException을 발생시킵니다.

Mojo mojo = (Mojo) descriptor.getMojo(); 

descriptor#getMojo() 유형 Mojo의 객체를 반환하지만 방법은 Object를 반환합니다. 어떻게 할 수 있니?

추가 정보가 필요한 경우 알려주십시오.

클래스 로딩에 대한 모든 이론을 읽었지만 이에 대한 적절한 해결책을 지정한 사람은 없습니다.

+0

, 당신이 할 경우 발생하는 :

ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = null; try { out = new ObjectOutputStream(bos); out.writeObject(cachedValue); byte b[] = bos.toByteArray(); //Store in DB, file wherever here using b[]. I am not writing code to store it as it may vary in your requirement. } catch (IOException e) { e.printStackTrace(); } 

는 바이트 배열에서 읽기'객체 descriptor.getMojo() = O를; System.out.println (o.getClass);'두 개의 다른 클래스 로더? – Bringer128

+0

여기서 가장 중요한 질문은 다음과 같습니다. * 실제로 * 여기 * 달성하려고 노력하고 있습니까? 이것은 학문적 인 운동입니까, 아니면이 상황을 뒷받침하는 실제 사용 사례입니까? –

+0

@ Bringer128 동일한 클래스 이름 package.Mojo를 반환합니다. getClass() 및 #cast (Object o) 메서드를 통해 캐스팅을 수행 할 수 있는지 여부를 생각하고 있었습니까? – ravana

답변

7

AFAIK, 아니요. 한 클래스 로더가 다른 클래스 로더에서로드 한 클래스의 객체를 캐스팅 할 수 없습니다.

  • 하나의 솔루션은 사용자 정의 클래스 로더가 사용할 클래스를로드하는 "공통"클래스 로더를 만드는 것입니다. 따라서 귀하의 경우에는 주어진 클래스를로드하는 새로운 클래스 로더가 생기며 사용자 정의 클래스 로더는이 클래스 로더를 확장합니다.
  • 또 다른 해결책은 두 클래스 로더간에 "serialize"상태를 전달하는 것입니다. 1 개의 인스턴스를 바이트 배열에 직렬화 해, 오브젝트 스트림의 역 직렬화에 의해 다른 클래스 로더의 오브젝트를 재구성합니다.
+0

나는 하나의 클래스 로더에서 다른 클래스 로더로 캐스팅하고 싶지 않습니다.하지만 그 캐스팅을 할 때 여기에서 일어나는 일입니다. 어떻게 같은 클래스 로더 내에서이 캐스팅을 수행 할 수 있습니까? (모조) descriptor.getMojo()가 작동하지 않습니다! – ravana

+0

이것은 설명 자의 "Mojo"인스턴스가 검색하려는 클래스 로더와 다른 클래스 로더에 의해로드 되었기 때문에 발생합니다. 여기에 더 많은 컨텍스트가 필요합니다. 응용 프로그램이 무엇입니까? 웹 응용 프로그램? 여기에 여러 스레드가 있습니까? –

+0

클래스 로딩을 위해 classworlds 1.1을 사용하는 단일 스레드에서 실행되는 Java 응용 프로그램입니다. – ravana

0

같은 클래스를로드하는 CloassLoader가 2 개있는 이유는 무엇입니까? 이는 프로그램상의 문제 일 수 있습니다. ClassLoader를 어딘가에 캐싱하고 잘못된 방식으로 다시 사용하는 것 같습니다. 그렇지 않은 경우 MultiClassLoader를 시도하십시오.

다른 여러 클래스 로더를 포함하는 MultiClassLoader를 만듭니다. 이 MultiClassLoader를 사용하여 원하는 모든 클래스를로드 할 수 있습니다. 하지만 클래스가로드 될 때가 아니라 처음에 이러한 MultiClassLoader를 만들어야합니다.

public class MultiClassLoader extends ClassLoader 

클래스 로더 컬렉션이 있고 findClass (...)에서는 등록 된 모든 로더를 반복합니다.

protected Class findClass(String aName) throws ClassNotFoundException { 
    for (Iterator iter = multiLoaders.iterator(); iter.hasNext();) { 
     ClassLoader tmpLoader = (ClassLoader)iter.next(); 
     try { 
     return tmpLoader.loadClass(aName); 
     } catch (ClassNotFoundException e) { 
     } 
    } 
    throw new ClassNotFoundException(aName); 
} 
+0

불행히도 클래스 로더를 변경할 수있는 능력이 없습니다. 두 가지 모두에 액세스 할 수 있지만 MultipleClassloader와 같은 것을 만들 수는 없습니다! – ravana

+0

getClass() 메서드는 클래스와 클래스 로더를 모두 포함하는 클래스를 반환합니까? 그렇다면 이와 같은 메커니즘을 사용하여이를 수행 할 수있는 방법이 있습니까? – ravana

+0

나는이 해결책을보고 있었다. 다른 방법으로 사용할 수 있습니다. 나는 하나 더 자세하게 알고 싶다. 예, findClass 메소드를 통해 Class 객체를 얻었습니다. 그럼 내가 뭘해야하지? 전에 말했듯이이 객체에 내 객체를 던져야합니다. Mojo = class.cast (object)는 클래스 # cast가 Object 유형의 객체를 반환한다고 생각하므로 컴파일러 오류가 발생합니다. – ravana

0

가장 쉬운 방법은 리플렉션을 사용하는 것입니다. 이렇게하면 "정상"코드로 할 수있는 모든 것을 할 수 있습니다.

+0

알겠습니다. 주어진 코드는 리플렉션을 사용합니다. 그러나 나는 반성에 대한 지식이 매우 제한적이다. 대답에 간단한 해결책을 추가 할 수 있습니까? 그것은 많은 도움이 될 것입니다! – ravana

+0

리플렉션을 사용할 때 간단한 해결책이 없습니다. 그것은 매우 지루합니다 : ( –

1

반사가 그렇게 나쁘지 않고 여기에 적합합니다.
이것은 Maven 플러그인입니까, BTW입니까? - 특히 예외 처리 - 그러나 이것은 당신이 필요로하는 자바 독에 당신을지도한다

Mojo mojo = (Mojo)descriptor.getClass().getMethod("getMojo").invoke(descriptor); 

내가 많이 밖으로 떠날거야 :

당신은 같은 것을 할 것입니다. 그것은 꽤 좋지만,주의 깊게 읽으십시오.

두 개의 모조 클래스가있는 경우 캐스트가 중단되며 악곡 - 트윈 모조와 관련된 작업을 수행하려면 더 많은 리플렉션을 수행해야합니다.

+0

실제로 이것은 메이븐 플러그인입니다. 어떤 javadoc이 무엇을 의미합니까? – ravana

+0

관련 클래스 및 메소드 javadoc. –

0

개체 대신 바이트 배열을 저장하는 것이 더 좋은 옵션이라고 생각합니다. deserliazing하는 동안 바이트 배열을 다시 가져오고 객체로 변환합니다.

동일한 문제와 바이트 배열 접근 방식이 적용되었습니다. 인스턴스에서

ByteArrayInputStream bis = new ByteArrayInputStream(<<read byte[] where you stored earlier>>); 
    ObjectInput in = null; 

    try { 
     in = new ObjectInputStream(bis); 
     <Your Class >cachedRes = (Your Class) in.readObject(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
    } 
관련 문제