投射到同一个类时发生ClassCastException

我有2个不同的Java项目,一个有2个类: dynamicbeans.DynamicBean2dynamicbeans.DynamicBean2

在另一个项目上,我dynamic加载这两个类并将它们存储在一个Object

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

然后我继续使用validatorClass.newInstance()创build一个Validator对象,并将其存储在validator然后使用beanClass.newInstance()创build一个bean对象,并将其添加到会话中。

 portletRequest.setAttribute("DynamicBean2", bean); 

Form项目的生命周期中,我调用validator.validate() ,从会话中加载先前创build的bean对象(我​​正在运行Websphere Portal Server)。 当我尝试将这个对象转换回到DynamicBean2它会失败并出现ClassCastExceptionexception。

当我将对象从会话中拉出时使用

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

并使用.getClass()检查它的类我得到dynamicbeans.DynamicBean2 。 这是我想要将它转换为类,但是当我尝试我得到ClassCastException。

任何理由,我得到这个?

我并不完全遵循你对程序stream程的描述,但是通常当你得到ClassCastExceptions时,你不能解释你已经用一个类加载器加载了这个类,然后尝试把它转换到另一个类加载器加载的同一个类。 这将不起作用 – 它们由JVM中的两个不同的Class对象表示,并且转换将失败。

有一篇关于WebSphere中的类加载的文章 。 我不能说它是如何适用于你的应用程序,但有一些可能的解决scheme。 我至less可以想到:

  1. 手动更改上下文类加载器。 要求你实际上可以得到一个适当的类加载器的引用,这在你的情况下可能是不可能的。

     Thread.currentThread().setContextClassloader(...); 
  2. 确保该类由层次结构中较高的类加载器加载。

  3. 序列化和反序列化对象。 (呸!)

但是,对于你的特殊情况,可能有更合适的方法。

类对象被加载到不同的类加载器中,因此在每个类中创build的实例被视为“不兼容”。 在使用许多不同的类加载器和传递对象的环境中,这是一个常见的问题。 这些问题很容易在Java EE和门户环境中出现。

投射一个类的实例需要链接到被转换对象的类与当前线程上下文类加载器加载的类相同。

我从另一个EJB的EJB查询也遇到同样的问题。 我解决了在EJB类configuration中添加@Remote(MyInterface.class)的问题

尝试使用Apache Commons Digester从XML创build对象列表时遇到了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 } 

如上所述,原因是蒸煮器不使用与程序的其余部分相同的ClassLoader。 我在JBoss中运行了这个程序,结果commons-digester.jar不在JBoss的lib目录下,而是在一个webapp的lib目录下。 将jar复制到mywebapp / WEB-INF / lib中也解决了这个问题。 另一个解决scheme是组装一个名为digester.setClassLoader(MyTemplate.class.getClassLoader())的工具,但是在这种情况下,这个解决scheme非常糟糕。

在不同的机器上使用多个JBoss实例时,我遇到了同样的问题。 不好,我没有偶然发现这个post。
在不同的机器上部署了工件,其中两个声明了相同名称的类加载器。我更改了其中一个类加载器名称,并且所有工作都很好=>注意复制和粘贴!

为什么不抛出ClassCastException抛出涉及的类加载器? – 我认为这将是非常有用的信息。
有谁知道今后是否会有这样的事情? 需要检查20-30个文物的class级装载者是不是很愉快。 还是有什么我错过了例外文本?

编辑 :我编辑了META-INF / jboss-app.xml文件并更改了加载器的名称,这个想法是有一个唯一的名字。 在工作中,我们使用artifact id(唯一)与maven({$ version})插入的版本相结合。
使用dynamic字段只是可选的,但如果你想部署同一个应用程序的不同版本的话。

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

你可以在这里find一些信息: https : //community.jboss.org/wiki/ClassLoadingConfiguration

我有同样的问题,我终于在java.net上find了一个解决方法:

将所有org.eclipse.persistence jar文件从glassfish4/glassfish/modules复制到WEB-INF/lib 。 然后进入你的glassfish-web.xml ,并将class-delegate设置为false

为我工作!

我和JAXB和JBoss AS 7.1有类似的问题。 这里描述的问题和解决scheme如下: javax.xml.bind.JAXBException:类***,也没有任何它的超类是这个上下文已知的 。 给出的exception是org.foo.bar.ValueSet不能转换为org.foo.bar.ValueSet

我在野蛮的EJB上遇到了同样的问题,EJB正在返回一个对象列表,并有一个远程和本地接口。 我错误地使用了Local接口,直到你尝试在列表中强制转换对象的时候,这个接口才工作得很好。

本地/远程接口:

 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周​​围的正确的spring包装:

 <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,您可以将其更改为$ Local,并且它将会findLocal接口,并且也可以在没有任何问题的情况下执行方法(来自同一个容器上的单独应用程序),但是模型对象不会被封送如果您错误地使用本地接口,则会从另一个类加载器中删除。

另一种select:

在weblogic中发生在我身上,但我想也可能发生在其他服务器 – 如果你(只)“发布”,因此你的一些类被重新加载。 相反,“干净”,所有的类将重新加载在一起。