转换为同一个类时出现ClassCastException

Jai*_*cia 51 java reflection classcastexception websphere-portal

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

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

class Form {
    Class beanClass;
    Class validatorClass;
    Validator validator;
}
Run Code Online (Sandbox Code Playgroud)

然后我继续创建一个Validator对象validatorClass.newInstance()并使用它validator然后我创建一个bean对象并使用beanClass.newInstance()并将其添加到会话中.

portletRequest.setAttribute("DynamicBean2", bean);
Run Code Online (Sandbox Code Playgroud)

Form项目的生命周期中,我调用validator.validate()从会话中加载先前创建的bean对象(我​​正在运行Websphere Portal Server).当我尝试将此对象强制转换为DynamicBean2失败并出现ClassCastException时.

当我将对象拉回会话时使用

faces.getApplication().createValueBinding("#{DynamicBean2}").getValue(faces);
Run Code Online (Sandbox Code Playgroud)

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

我得到这个的原因是什么?

wax*_*ing 58

我不太关注你对程序流的描述,但通常当你得到ClassCastExceptions时你无法解释你已经用一个类加载器加载了类,然后尝试将它转换为由另一个类加载器加载的同一个类.这不起作用 - 它们由JVM中的两个不同的Class对象表示,并且转换将失败.

一篇关于WebSphere中的类加载文章.我不能说它如何适用于您的应用程序,但有许多可能的解决方案.我至少可以想到:

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

    Thread.currentThread().setContextClassLoader(...);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 确保该类由层次结构中较高的类加载器加载.

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

但是,对于您的特定情况,可能有更合适的方式.

  • 我的猜测(我没有门户服务器的经验)是你在不同的portlet中加载类,每个portlet都有自己的类加载器.然后,您将实例放入会话对象中,当您从错误的portlet(从中创建它)中检索它时,您将获得异常.我猜(根据WAS经验)你需要将jar放在类加载层次结构中较高的类中,以便它由两个portlet类加载器的父级加载. (3认同)
  • 即2号,详情. (2认同)

K.N*_*las 17

spring-boot-devtools在我的 Springboot 项目中添加依赖项后,我遇到了这个问题。我删除了依赖项,问题就消失了。在这一点上,我最好的猜测是spring-boot-devtools引入了一个新的类加载器,并且在某些线程没有使用新的类加载器的某些情况下,这会导致不同类加载器之间的类转换问题。

参考:一个与Spring boot devtools相关的推土机地图异常

  • 谢谢!这在 2022 年仍然是一个问题。不知道为什么他们还没有解决它 (2认同)

Rob*_*bin 12

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

转换类的实例要求链接到正在转换的对象的类与当前线程上下文类加载器加载的类相同.

  • 这取决于您正在操作的环境.如果您使用单例来缓存信息,并且您将数据从同一EAR中的两个不同的Web应用程序放入此缓存中,则每个Web应用程序都可以创建自己的类加载器,并且当从另一个webapp从此缓存中检索item,它将导致ClassCastException.在这些环境中共享内存数据可能非常棘手,因此您必须了解正在加载类的位置才能使其工作. (2认同)