java - 由于不同的类加载器,在同一个耳朵中从两个不同的 war 中加载相同的类时出现 ClassCastException

标签 java weblogic classloader oracle-adf ear

我正在开发一个现有的 ADF 应用程序,其中部署在 weblogic 上的 EAR 中有两个不同的项目模块。
1. 具有 VO、EO 和 AM 的模型项目(包含应用模块实现)
2. UI项目(使用模型项目的构建文件为此项目创建war)

我添加了另一个 war 文件,用于与 UI 一起启用休息服务。不同 war 的原因是 UI war 需要 Web 身份验证,而我们希望通过提供多 token 身份验证来绕过 Rest war 。 所以现在我们有两场 war 和三个模块。
1. 样板工程
2.UI项目
3. Rest 项目(使用 UI 项目和 Model 项目中的构建文件)

现在的问题是应用程序模块实现是使用

检索的 ApplicationModuleHandle amHandle = Configuration.createRootApplicationModuleHandle("**.**.classpackage","config_name");

amImpl = (MyAMImpl) amHandle.useApplicationModule();

如果其中一场 war 创建了我的 MyAMImpl 对象,另一场 war 则获得

ClassCastException.

我的问题是是否有任何方法可以使用weblogic-application.xml使用相同的类加载器来加载这两个 war 。或代码级别的任何其他配置。

附注:我避免使用自定义类加载器弄乱我的代码,或者在应用程序代码中强制使用相同的类加载器,因为它是现有应用程序。

非常感谢任何帮助。

编辑: 首先有另一个包含单例对象的模块。为了进一步清晰起见,这是一个 Quartz Singleton。 UI 项目包含一个调用应用程序模块的触发器监听器。

因此,我通过大量故障排除找到了原因和解决方案。

原因:两次 war 都使用单独的类加载器,并且会创建不同的 Quartz Singleton 实例。每个也都有自己的 TriggerListener 实例。
因此,当其中一个模块调用 QuartzScheduler 和 Trigger Listener 时,它会创建一个应用程序模块(该模块持久化在应用程序中,不会被释放)。
现在,当第二个应用程序调用 QuartzSingleton 时,将为第二个类加载器创建相同的新实例和触发监听器,但返回应用程序模块的相同实例。由于第二个类加载器不知道返回的应用程序模块,因此它会抛出 ClassCastException。

解决方案:在 EAR 级别添加包含 Quartz Scheduler 的项目,并在 war 项目中添加该项目的构建输出(这样它们就不会抛出编译时异常)。这将使整个应用程序能够使用应用程序的类加载器(实际上是两场 war 的父类加载器)拥有一个 Quartz Scheduler Singleton 实例。这使得两个 war 都能够在父类加载器中找到该类,并且不会抛出异常,因为现在所有三个实例,即 Quartz Scheduler Singleton、TriggerListener 和 Application Module 都驻留在同一个类加载器中。

附注:我知道一开始并没有太多解释,因为我自己也不确定原因。对此表示诚挚的歉意。该应用程序存在明显的设计缺陷。但它仍然有。希望有人觉得这很有用

最佳答案

我也在查询中添加了原因和解决方案。

原因:两次 war 都使用单独的类加载器,并且会创建不同的 Quartz Singleton 实例。每个也都有自己的 TriggerListener 实例。 因此,当其中一个模块调用 QuartzScheduler 和 Trigger Listener 时,它会创建一个应用程序模块(该模块保留在应用程序中并且不会被释放)。 现在,当第二个应用程序调用 QuartzSingleton 时,将为第二个类加载器创建相同的新实例和触发监听器,但将返回应用程序模块的相同实例。由于第二个类加载器不知道返回的应用程序模块,因此它会抛出 ClassCastException。

解决方案:在 EAR 级别添加包含 Quartz Scheduler 的项目,并在 war 项目中添加该项目的构建输出(这样它们就不会抛出编译时异常)。这将使整个应用程序能够使用应用程序的类加载器(实际上是两场 war 的父类加载器)拥有一个 Quartz Scheduler Singleton 实例。这使得两个 war 都能够在父类加载器中找到该类,并且不会抛出异常,因为现在所有三个实例,即 Quartz Scheduler Singleton、TriggerListener 和 Application Module 都驻留在同一个类加载器中。

关于java - 由于不同的类加载器,在同一个耳朵中从两个不同的 war 中加载相同的类时出现 ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53910219/

相关文章:

java - s ParseUser.CurrentUser() 在来自客户端的 Parses 服务器上不同

spring - Tomcat 迁移到 WebLogic12

java - 在 tomcat 上部署应用程序时加载的类过多

java - 使用 Spring Boot 2 的 PropertiesLauncher(并运行 WAR 存档)

java - 为 maven 指定类路径

java - 在 JVM 运行时查找类

java - Android apache Poi ArrayAdapter

java - JLabel 位置不起作用,无法选择位置

java - 为用户显示更好的错误消息

java - SSLException:不支持的记录版本未知