문제

2 개의 다른 Java 프로젝트가 있으며 하나는 2 개의 클래스가 있습니다. dynamicbeans.DynamicBean2 그리고 dynamic.Validator.

다른 프로젝트에서, 나는이 두 수업을 동적으로로드하고 Object

class Form {
    Class beanClass;
    Class validatorClass;
    Validator validator;
}

그런 다음 계속해서 a Validator 객체 사용 validatorClass.newInstance() 그리고 그것을 저장하십시오 validator 그런 다음 Bean 객체를 만들고 사용합니다 beanClass.newInstance() 세션에 추가하십시오.

portletRequest.setAttribute("DynamicBean2", bean);

수명주기 동안 Form 프로젝트, 전화 validator.validate() 세션에서 이전에 생성 된 Bean 객체를로드합니다 (WebSphere Portal Server를 실행 중입니다). 이 개체를 다시 캐스팅하려고 할 때 DynamicBean2 ClassCastException으로 실패합니다.

내가

faces.getApplication().createValueBinding("#{DynamicBean2}").getValue(faces);

그리고 그것을 사용하는 클래스를 확인하십시오 .getClass() 나는 얻다 dynamicbeans.DynamicBean2. 이것은 내가 캐스팅하고 싶은 수업이지만, 시도 할 때 ClassCastException을 얻습니다.

내가 이것을 얻는 이유는 무엇입니까?

도움이 되었습니까?

해결책

프로그램 흐름에 대한 설명을 따르지는 않지만 일반적으로 ClassCastExceptions를 얻을 때 한 클래스 로더로 클래스를로드 한 다음 다른 클래스 로더로로드 된 동일한 클래스로 캐스팅하려고 시도 할 수 없습니다. 이것은 작동하지 않습니다. JVM 내부의 두 개의 다른 클래스 객체로 표시되며 캐스트가 실패합니다.

있습니다 WebSphere의 클래스로드에 관한 기사. 응용 프로그램에 어떻게 적용되는지 말할 수는 없지만 여러 가지 가능한 솔루션이 있습니다. 나는 적어도 생각할 수있다 :

  1. 컨텍스트 클래스 로더를 수동으로 변경하십시오. 실제로 적절한 클래스 로더에 대한 참조를 얻을 수 있어야합니다.이 경우에는 불가능할 수 있습니다.

    Thread.currentThread().setContextClassLoader(...);
    
  2. 클래스가 계층 구조에서 더 높은 클래스 로더에 의해로드되어 있는지 확인하십시오.

  3. 객체를 직렬화하고 사로화하십시오. (왝!)

그래도 특정 상황에 더 적절한 방법이있을 수 있습니다.

다른 팁

클래스 객체는 다른 클래스 로더에로드되었으므로 각 클래스에서 생성 된 인스턴스는 '호환되지 않는'것으로 간주됩니다. 이것은 다양한 클래스 로더가 사용되고 객체가 통과되는 환경에서 일반적인 문제입니다. 이러한 문제는 Java EE 및 포털 환경에서 쉽게 발생할 수 있습니다.

클래스의 인스턴스를 캐스팅하려면 주조되는 객체에 링크 된 클래스가 현재 스레드 컨텍스트 클래스 로더에 의해로드 된 것과 동일해야합니다.

Apache Commons Digester를 사용하여 XML에서 객체 목록을 작성하려고 할 때 A2AclassCastException 문제가 발생했습니다.

List<MyTemplate> templates = new ArrayList<MyTemplate>();
Digester digester = new Digester();
digester.addObjectCreate("/path/to/template", MyTemplate.class);
digester.addSetNext("/path/to/template", "add");
// Set more rules...
digester.parse(f); // f is a pre-defined File

for(MyTemplate t : templates) { // ClassCastException: Cannot cast mypackage.MyTemplate to mypackage.MyTemplate
    // Do stuff
}

위에서 언급 한 바와 같이, 원인은 소화조가 프로그램의 나머지 부분과 동일한 클래스 로더를 사용하지 않기 때문입니다. 나는 이것을 Jboss에서 실행했고, Commons-Digester.jar는 JBoss의 LIB 디렉토리가 아니라 WebApp의 LIB 디렉토리에 있다는 것이 밝혀졌습니다. JAR을 MyWebApp/Web-Inf/Lib에 복사하면 문제가 해결되었습니다. 또 다른 솔루션은 Casll Digester.setClassLoader (MyTemplate.class.getClassLoader ())이지만이 맥락에서 상당히 추악한 솔루션처럼 느껴집니다.

다른 기계에서 여러 JBOSS 인스턴스를 사용하는 동안 같은 문제가있었습니다. 나쁘게 나는이 게시물을 일찍 우연히 발견하지 못했습니다.
다른 기계에 아티팩트가 배포되었고, 그 중 2 개는 동일한 이름을 가진 클래스 로더를 선언했습니다. 클래스 로더 이름 중 하나를 변경했으며 모든 것이 잘 작동했습니다 => 복사 및 붙여 넣기를 조심하십시오!

ClassScastException이 관련 클래스 로더를 언급하지 않는 이유는 무엇입니까? - 나는 그것이 매우 유용한 정보라고 생각합니다.
미래에 이와 같은 것이 있을지 아는 사람이 있습니까? 20-30 아티팩트의 클래스 로더를 확인 해야하는 것은 그리 즐겁지 않습니다. 아니면 예외 텍스트에서 놓친 것이 있습니까?

편집하다: 메타 -inf/jboss-app.xml 파일을 편집하고 로더의 이름을 변경했습니다. 아이디어는 고유 한 이름을 갖는 것입니다. 직장에서는 빌드 중에 Maven ({$ version})이 삽입 한 버전과 결합 된 아티팩트 ID (고유)를 사용합니다.
다이나믹 필드를 사용하는 것은 선택 사항 일뿐이지만 동일한 응용 프로그램의 다른 버전을 배포하려는 경우 도움이됩니다.

<jboss-app>
   <loader-repository> 
   com.example:archive=unique-archive-name-{$version}
   </loader-repository> 
</jboss-app>

여기에서 몇 가지 정보를 찾을 수 있습니다. https://community.jboss.org/wiki/classloadingconfiguration

같은 문제가 있었고 마침내 java.net에서 해결 방법을 찾았습니다.

모두 복사하십시오 org.eclipse.persistence jar 파일 glassfish4/glassfish/modules 에게 WEB-INF/lib. 그런 다음 당신의 입장 glassfish-web.xml, 그리고 설정 class-delegate 에게 false.

나를 위해 일했습니다!

JAXB와 JBOSS와 비슷한 문제가 7.1로 비슷했습니다. 문제와 솔루션은 다음과 같습니다. javax.xml.bind.jaxbexception : 클래스 *** 또는 그 슈퍼 클래스 가이 맥락에 알려져 있습니다.. 주어진 예외는 org.foo.bar.valueset이 org.foo.bar.valueset에 캐스트 할 수 없습니다.

나는 Wildfly EJB에서 같은 문제를 겪었고, EJB는 객체 목록을 반환하고 있으며 리모컨 및 로컬 인터페이스가 있습니다. 나는 목록에 객체를 캐스팅하려고 할 때까지 잘 작동하는 것을 실수로 로컬 인터페이스를 사용했습니다.

로컬/원격 인터페이스 :

public interface DocumentStoreService {

    @javax.ejb.Remote
    interface Remote extends DocumentStoreService {
    }

    @javax.ejb.Local
    interface Local extends DocumentStoreService {
    }

ejb bean :

@Stateless
public class DocumentStoreServiceImpl implements DocumentStoreService.Local, DocumentStoreService.Remote {

EJB 주변의 올바른 스프링 래퍼 :

<bean id="documentStoreService" class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
    <property name="jndiName" value="java:global/dpc/dpc-ejb/DocumentStoreServiceImpl!santam.apps.dpc.service.DocumentStoreService$Remote"/>
    <property name="businessInterface" value="santam.apps.dpc.service.DocumentStoreService$Remote"/>
    <property name="resourceRef" value="true" />
</bean>

$ remote를 참고하면이를 $ 로컬로 변경할 수 있으며 로컬 인터페이스를 잘 찾을 수 있으며 문제없이 메소드를 실행할 수 있지만 (동일한 컨테이너의 별도 응용 프로그램에서) 모델 객체는 마샬이 아니며 있습니다. 실수로 로컬 인터페이스를 사용하는 경우 다른 클래스 로더에서.

다른 옵션 :

Weblogic에서 나에게 일어 났지만 다른 서버에서도 일어날 수 있다고 생각합니다. "게시"하는 경우 일부 클래스가 다시로드됩니다. 대신 모든 클래스가 함께로드되도록 "청소"하십시오.

다른 EJB의 EJB 조회에도 같은 문제가있었습니다. EJB 클래스 구성에 @remote (myinterface.class)를 추가했습니다.

동일했다 my.package.MyClass cannot be cast to my.package.MyClass Wildfly 10.1에서, 내가 이해했듯이, 나는 그의 대답에 @emil lundberg가 묘사 한 것과 반대를했다.

나는 그것을 추가했다 기준 치수 (포함하는 my.package.MyClass) 에게 my.war/WEB-INF/jboss-deployment-structure.xml 의존성으로

<dependencies>
    ...
    <module name="my.package"/>
</dependencies>

해당 대응을 제거했습니다 항아리 ~에서 my.war/WEB-INF/lib, 전쟁을 재개 한 다음 코드는 예상대로 작동했습니다.

따라서 우리는 그것이 문제를 해결했는지 확인했습니다. 이제 업데이트 된 버전이 전쟁 조립 및 배포됩니다.

이것을 위해, 그 근원에서 전쟁, 추가해야합니다 <scope>provided</scope> 그것들을 위해 항아리 안에 pom.xml, 언제 my.war 다음에 수정/강화 코드가 주입 된 상태에서 다시 조립됩니다. 항아리 ~ 안으로 my.war/WEB-INF/lib.

의존성을 추가 한 후이 문제가 발생했습니다. spring-boot-devtools 내 스프링 부츠 프로젝트에서. 의존성을 제거하고 문제가 사라졌습니다. 이 시점에서 가장 좋은 추측은 그 것입니다 spring-boot-devtools 새로운 클래스 로더를 가져오고 일부 스레드에서 새 클래스 로더를 사용하지 않는 특정 경우 다른 클래스 로더간에 클래스 캐스팅 문제 문제가 발생합니다.

참조: Spring Boot DevTools와 관련된 도저 맵 예외

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top