我有两个不同的Java项目,一个有两个类:dynamicbeans.DynamicBean2
和dynamic.Validator
。
在另一个项目中,我动态加载这两个类并将它们存储在Object
class Form {
Class beanClass;
Class validatorClass;
Validator validator;
}
然后我继续使用Validator
创建一个validatorClass.newInstance()
对象并将其存储在validator
上,然后使用beanClass.newInstance()
创建一个bean对象并将其添加到会话。
portletRequest.setAttribute("DynamicBean2", bean);
在Form
项目的生命周期中,我调用validator.validate()
从会话中加载以前创建的bean对象(我正在运行Websphere Portal Server)。当我尝试将此对象强制转换为DynamicBean2
时,它失败并出现ClassCastException。
当我使用
将对象拉回会话时faces.getApplication().createValueBinding("#{DynamicBean2}").getValue(faces);
并使用.getClass()
检查其类别我得到dynamicbeans.DynamicBean2
。这是我要将它强制转换为的类,但是当我尝试获取ClassCastException时。
为什么我得到这个?
答案 0 :(得分:56)
我不太关注你对程序流的描述,但通常当你得到ClassCastExceptions时你无法解释你已经用一个类加载器加载了类,然后尝试将它转换为由另一个类加载器加载的同一个类。这不起作用 - 它们由JVM中的两个不同的Class对象表示,并且转换将失败。
有一个article about classloading in WebSphere。我不能说它如何适用于您的应用程序,但有许多可能的解决方案。我至少可以想到:
手动更改上下文类加载器。要求您实际上可以获得对适当的类加载器的引用,这在您的情况下可能是不可能的。
Thread.currentThread().setContextClassLoader(...);
确保该类由层次结构中较高的类加载器加载。
序列化和反序列化对象。 (呸!)
但是,对于您的特定情况,可能有更合适的方式。
答案 1 :(得分:12)
类对象被加载到不同的类加载器中,因此从每个类中创建的实例被视为“不兼容”。在使用许多不同类加载器并传递对象的环境中,这是一个常见问题。这些问题很容易出现在Java EE和门户环境中。
强制转换类的实例要求链接到正在转换的对象的Class与当前线程上下文类加载器加载的类相同。
答案 2 :(得分:2)
尝试使用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
}
如上所述,原因是消化器不使用与程序其余部分相同的ClassLoader。我在JBoss中运行它,结果发现commons-digester.jar不在JBoss的lib目录中,而是在webapp的lib目录中。将jar复制到mywebapp / WEB-INF / lib也解决了这个问题。另一个解决方案是casll digester.setClassLoader(MyTemplate.class.getClassLoader()),但在这种情况下,这感觉就像一个丑陋的解决方案。
答案 3 :(得分:0)
在不同的计算机上使用多个JBoss实例时遇到了同样的问题。糟透了,我之前没有发现这篇文章 在不同的机器上部署了工件,其中两个声明了类名相同的类加载器。我更改了一个类加载器名称,一切正常=>&gt;小心复制和粘贴!
为什么抛出的ClassCastException没有提到涉及的类加载器? - 我认为这将是非常有用的信息。
有谁知道将来是否会有这样的东西?需要检查20-30件文物的类装载器并不那么令人愉快。或者我在异常文本中遗漏了什么?
编辑:我编辑了META-INF / jboss-app.xml文件并更改了加载器的名称,其想法是拥有一个唯一的名称。在工作中,我们使用工件id(唯一)与maven({$ version})在构建期间插入的版本相结合。
使用动态字段只是可选字段,但如果要部署同一应用程序的不同版本,则会有所帮助。
<jboss-app>
<loader-repository>
com.example:archive=unique-archive-name-{$version}
</loader-repository>
</jboss-app>
您可以在此处找到一些信息:https://community.jboss.org/wiki/ClassLoadingConfiguration
答案 4 :(得分:0)
我有同样的问题,我终于找到了一个关于java.net的解决方法:
将所有org.eclipse.persistence jar
个文件从glassfish4/glassfish/modules
复制到WEB-INF/lib
。然后进入glassfish-web.xml
,并将class-delegate
设置为false
。
为我工作!
答案 5 :(得分:0)
我遇到了与JAXB和JBoss AS 7.1类似的问题。此处描述了问题和解决方案:javax.xml.bind.JAXBException: Class *** nor any of its super class is known to this context。给出的异常是org.foo.bar.ValueSet无法强制转换为org.foo.bar.ValueSet
答案 6 :(得分:0)
我在wildfly 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,它会发现Local接口就好了,并且执行方法没有任何问题(来自同一容器上的单独应用程序),但模型对象不是如果您错误地使用本地接口,则封送并来自不同的类加载器。
答案 7 :(得分:0)
另一种选择:
在weblogic中发生了我,但我想它也可能发生在其他服务器上 - 如果你这样做(只是)&#34;发布&#34;因此,你的一些课程被重新加载。而是&#34;清洁&#34;所以所有的课程都会重新加载。
答案 8 :(得分:0)
我从另一个EJB查找EJB时出现同样的问题。 我解决了将@Remote(MyInterface.class)添加到EJB类配置
答案 9 :(得分:0)
在WildFly 10.1上具有相同的my.package.MyClass cannot be cast to my.package.MyClass
,据我了解,我所做的与@Emil Lundberg在他的回答中所描述的相反。
我已将{strong>模块(其中包含my.package.MyClass
)添加到my.war/WEB-INF/jboss-deployment-structure.xml
作为依赖项
<dependencies>
...
<module name="my.package"/>
</dependencies>
并从my.war/WEB-INF/lib
中删除了相应的 jar ,重新部署了WAR,然后代码按预期工作。
因此,我们确保可以解决问题。现在,我们需要确保问题不会再次出现,例如,当组装并部署更新版本的 WAR 时。
为此,在那些 War 的来源中,需要为<scope>provided</scope>
中的这些 jar 添加pom.xml
,以便在下次将my.war
重新组装并注入修复/增强代码时,它不会将此 jar 捆绑到my.war/WEB-INF/lib
中。
答案 10 :(得分:0)
在Springboot项目中向spring-boot-devtools
添加依赖项后,我遇到了这个问题。我删除了依赖性,问题消失了。目前,我的最佳猜测是spring-boot-devtools
引入了一个新的类加载器,并且在某些情况下某些线程未使用新的类加载器时,会导致不同类加载器之间发生类转换问题。