简体   繁体   English

强制转换到同一类时出现 ClassCastException

[英]ClassCastException when casting to the same class

I have 2 different Java projects, one has 2 classes: dynamicbeans.DynamicBean2 and dynamic.Validator .我有2个不同的Java项目,一个有2类: dynamicbeans.DynamicBean2dynamic.Validator

On the other project, I load both of these classes dynamically and store them on an Object在另一个项目中,我动态加载这两个类并将它们存储在一个Object

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

I then go ahead and create a Validator object using validatorClass.newInstance() and store it on validator then I create a bean object as well using beanClass.newInstance() and add it to the session.然后我继续使用validatorClass.newInstance()创建一个Validator对象并将其存储在validator然后我也使用beanClass.newInstance()创建一个 bean 对象并将其添加到会话中。

portletRequest.setAttribute("DynamicBean2", bean);

During the lifecycle of the Form project, I call validator.validate() which loads the previously created bean object from the session (I'm running Websphere Portal Server).Form项目的生命周期中,我调用了validator.validate() ,它从会话中加载先前创建的 bean 对象(我正在运行 Websphere Portal Server)。 When I try to cast this object back into a DynamicBean2 it fails with a ClassCastException.当我尝试将此对象转换回DynamicBean2它失败并显示 ClassCastException。

When I pull the object back out of the session using当我使用

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

and check the class of it using .getClass() I get dynamicbeans.DynamicBean2 .并使用.getClass()检查它的类我得到dynamicbeans.DynamicBean2 This is the class I want to cast it to however when I try I get the ClassCastException.这是我想将它投射到的类,但是当我尝试时,我得到了 ClassCastException。

Any reason why I'm getting this?我得到这个的任何原因?

I am not quite following your description of the program flow, but usually when you get ClassCastExceptions you cannot explain you have loaded the class with one classloader then try to cast it to the same class loaded by another classloader.我不太了解您对程序流程的描述,但通常当您收到 ClassCastExceptions 时,您无法解释您已使用一个类加载器加载了该类,然后尝试将其转换为由另一个类加载器加载的同一个类。 This will not work - they are represented by two different Class objects inside the JVM and the cast will fail.这将不起作用 - 它们由 JVM 内的两个不同的 Class 对象表示,并且转换将失败。

There is an article about classloading in WebSphere .一篇关于 WebSphere 中的类加载文章 I cannot say how it applies to your application, but there are a number of possible solutions.我不能说它如何适用于您的应用程序,但有许多可能的解决方案。 I can think of at least:我至少能想到:

  1. Change the context class loader manually.手动更改上下文类加载器。 Requires that you can actually get a reference to an appropriate class loader, which may not be possible in your case.要求您实际上可以获得对适当类加载器的引用,这在您的情况下可能是不可能的。

     Thread.currentThread().setContextClassLoader(...);
  2. Make sure the class is loaded by a class loader higher in the hierarchy.确保该类由层次结构中更高的类加载器加载。

  3. Serialize and deserialize the object.序列化和反序列化对象。 (Yuck!) (呸!)

There is probably a more appropriate way for your particular situation though.不过,对于您的特定情况,可能有更合适的方法。

I was getting this problem after adding a dependency to spring-boot-devtools in my Springboot project.在我的 Springboot 项目中添加对spring-boot-devtools的依赖后,我遇到了这个问题。 I removed the dependency and the problem went away.我删除了依赖项,问题就消失了。 My best guess at this point is that spring-boot-devtools brings in a new classloader and that causes the issue of class casting problems between different classloaders in certain cases where the new classloader is not being used by some threads.在这一点上,我最好的猜测是spring-boot-devtools了一个新的类加载器,并且在某些线程未使用新类加载器的某些情况下,这会导致不同类加载器之间的类转换问题。

Reference: A dozer map exception related to Spring boot devtools参考: 一个与Spring boot devtools相关的推土机地图异常

The class objects were loaded in different classloaders, therefore the instances created from in each of classes are seen as 'incompatible'.类对象在不同的​​类加载器中加载,因此在每个类中创建的实例被视为“不兼容”。 This is a common issue in a an environment where there are many different classloaders being used and objects are being passed around.在使用许多不同的类加载器并且正在传递对象的环境中,这是一个常见问题。 These issues can easily arise in Java EE and portal environments.这些问题很容易在 Java EE 和门户环境中出现。

Casting an instance of a class requires that the Class linked to the object being casted is the same as the one loaded by the current thread context classloader.转换类的实例要求链接到被转换对象的类与当前线程上下文类加载器加载的类相同。

I got the A2AClassCastException problem when trying to create a List of objects from XML using Apache Commons Digester.我在尝试使用 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
}

As stated above, the cause is that the digester doesn't use the same ClassLoader as the rest of the program.如上所述,原因是摘要器没有使用与程序其余部分相同的类加载器。 I ran this in JBoss, and it turned out that commons-digester.jar was not in JBoss's lib directory, but rather in a webapp's lib directory.我在 JBoss 中运行了这个,结果发现 commons-digester.jar 不在 JBoss 的 lib 目录中,而是在 webapp 的 lib 目录中。 Copying the jar into mywebapp/WEB-INF/lib also solved the problem.将 jar 复制到 mywebapp/WEB-INF/lib 也解决了问题。 Another solution was to casll digester.setClassLoader(MyTemplate.class.getClassLoader()), but that feels like quite an ugly solution in this context.另一种解决方案是调用digester.setClassLoader(MyTemplate.class.getClassLoader()),但在这种情况下,这感觉是一个非常丑陋的解决方案。

Had the same my.package.MyClass cannot be cast to my.package.MyClass on WildFly 10.1 and, as I understand, I did the opposite to what @Emil Lundberg described in his answer.在 WildFly 10.1 上my.package.MyClass cannot be cast to my.package.MyClass相同的my.package.MyClass cannot be cast to my.package.MyClass ,据我所知,我做了与@Emil Lundberg 在他的回答中描述的相反的事情。

I have added the module (which contains my.package.MyClass ) to my.war/WEB-INF/jboss-deployment-structure.xml as a dependency我已将模块(包含my.package.MyClass )添加到my.war/WEB-INF/jboss-deployment-structure.xml作为依赖项

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

and removed the corresponding jar from my.war/WEB-INF/lib , re-deployed the WAR and then the code worked as expected.并从my.war/WEB-INF/lib删除相应的jar ,重新部署 WAR,然后代码按预期工作。

Thus, we made sure it solves the issue.因此,我们确保它解决了这个问题。 Now, we need to make sure the issue won't come back, for example, when the updated version of WAR will be assembled and deployed.现在,我们需要确保问题不会再次出现,例如,何时组装和部署更新版本的WAR

For this, in the sources of those WAR , it is required to add <scope>provided</scope> for those jar in pom.xml , so that when my.war is re-assembled next time with the fix/enhancement code injected, it will not bundle this jar into my.war/WEB-INF/lib .为此,在那些WAR的源代码中,需要在pom.xml为那些jar添加<scope>provided</scope> ,以便下次重新组装my.war时注入修复/增强代码,它不会将此jar捆绑到my.war/WEB-INF/lib

I had the same issue, and I finally found a workaround on java.net :我遇到了同样的问题,我终于在 java.net 上找到了解决方法:

Copy all org.eclipse.persistence jar files from glassfish4/glassfish/modules to WEB-INF/lib .将所有org.eclipse.persistence jar文件从glassfish4/glassfish/modules复制到WEB-INF/lib Then go in your glassfish-web.xml , and set class-delegate to false .然后进入你的glassfish-web.xml ,并将class-delegate设置为false

Worked for me !为我工作!

I had a similar issue with JAXB and JBoss AS 7.1.我在 JAXB 和 JBoss AS 7.1 上遇到了类似的问题。 The issue and solution are described here: javax.xml.bind.JAXBException: Class *** nor any of its super class is known to this context .此处描述了问题和解决方案: javax.xml.bind.JAXBException: Class *** 或其任何超类都不为该上下文所知 The exception that was given was org.foo.bar.ValueSet cannot be cast to org.foo.bar.ValueSet给出的例外是 org.foo.bar.ValueSet 不能转换为 org.foo.bar.ValueSet

I had the same issue on a wildfly EJB, The EJB was returning a list of Objects and has an remote and a local interface.我在 Wildfly EJB 上遇到了同样的问题,EJB 正在返回一个对象列表,并且有一个远程和一个本地接口。 I used the Local interface by mistake what was working just fine up until the point you try to cast the objects in the list.我错误地使用了 Local 接口,直到您尝试将对象转换为列表中的对象之前,它一直运行良好。

Local/Remote interface:本地/远程接口:

public interface DocumentStoreService {

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

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

The EJB bean: EJB bean:

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

The correct spring wrapper around the EJB: 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>

Note the $Remote, You can change this to $Local and it will find the Local interface just fine, and also execute the methods without any issue (from a separate application on the same container), but the model objects are not marshaled and are from a different class loader if you use the local interface by mistake.请注意 $Remote,您可以将其更改为 $Local,它会发现 Local 接口很好,并且还可以毫无问题地执行方法(来自同一容器上的单独应用程序),但模型对象未编组,而是如果您错误地使用本地接口,则从不同的类加载器。

Another option:另外一个选项:

Happened to me in weblogic, but I guess it can happen in other servers as well - if you do (just) "Publish" and therefor some of your classes are re-loaded.在 weblogic 中发生在我身上,但我想它也可能发生在其他服务器上 - 如果你(只是)“发布”并且因此你的一些类被重新加载。 Instead do "Clean" so all the classes will re-loaded together.而是执行“清理”,以便所有类将重新加载在一起。

I had same problem with an EJB lookup from another EJB.我在从另一个 EJB 查找 EJB 时遇到了同样的问题。 I solved adding @Remote(MyInterface.class) to EJB class configuration我解决了将@Remote(MyInterface.class) 添加到 EJB 类配置的问题

I had the same issue while using several JBoss instances on different machines.我在不同的机器上使用多个 JBoss 实例时遇到了同样的问题。 To bad I didn't stumble across this post earlier.糟糕的是,我之前没有偶然发现这篇文章。
There were artifacts deployed on different machines, two of them declared class loaders with identical name.I changed one of the classloader names and everything worked fine => Beware of Copy&Paste!在不同的机器上部署了工件,其中两个声明了具有相同名称的类加载器。我更改了一个类加载器名称,一切正常 => 小心复制和粘贴!

Why doesn't the ClassCastException thrown mention the involved class loaders?为什么抛出的 ClassCastException 没有提到所涉及的类加载器? - I think that would be very useful information. - 我认为这将是非常有用的信息。
Does anyone know if there will be anything like this available in the future?有谁知道将来是否会有这样的东西可用? Needing to check the class loaders of 20-30 Artifacts is not that pleasant.需要检查 20-30 个工件的类加载器并不是那么愉快。 Or is there something I missed in the exception text?或者我在异常文本中遗漏了什么?

EDIT : I edited the META-INF/jboss-app.xml file and changed the name of the loader, the idea is to have a unique name.编辑:我编辑了 META-INF/jboss-app.xml 文件并更改了加载程序的名称,想法是要有一个唯一的名称。 At work we use the artifact id(unique) combined with the version inserted by maven({$version}) during the build.在工作中,我们将工件 id(unique) 与构建期间由 maven({$version}) 插入的版本结合使用。
Using dynamic fields is only optional but helps if you want to deploy different versions of the same application.使用动态字段只是可选的,但如果您想部署同一应用程序的不同版本,则会有所帮助。

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

You can find some info here: https://community.jboss.org/wiki/ClassLoadingConfiguration你可以在这里找到一些信息: https : //community.jboss.org/wiki/ClassLoadingConfiguration

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 强制转换为同一对象时发生ClassCastException - ClassCastException when casting to same object 转换为同一类时出现java.lang.ClassCastException-ClassLoader问题 - java.lang.ClassCastException when casting to the same class - ClassLoader issues 我的类加载器有什么问题? 投射到同一个类时出现 ClassCastException! - What is wrong with my classloader? ClassCastException when casting to the same class! 转换回原始类时出现ClassCastException错误 - ClassCastException error when casting back to original class 将 Object 转换为 String 时出现 ClassCastException,但将 Object 转换为自定义类时没有 ClassCastException - ClassCastException when casting Object to String, but no ClassCastException when casting Object to Custom class 将基础类对象转换为扩展基础类的类时的ClassCastException - ClassCastException when casting a base class object to an class that extends base class 投射 TargetDataLine 时出现 ClassCastException - ClassCastException when casting TargetDataLine 将 Class.forName 对象转换为此对象实现的接口时出现 ClassCastException - ClassCastException when casting Class.forName object to interface implemented by this object 强制转换为对象数组时发生ClassCastException - ClassCastException when casting to object array 将数组强制转换为readObject时发生ClassCastException - ClassCastException when casting array to readObject
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM