【问题标题】:Oracle JDBC driver conflictOracle JDBC 驱动冲突
【发布时间】:2013-06-16 13:46:48
【问题描述】:

JBoss EAP 6.1 独立服务器

部署为 war 文件的应用程序引发运行时异常

java.lang.ClassCastException: oracle.sql.ARRAY cannot be cast to oracle.sql.ARRAY

一行

oracle.sql.ARRAY obj = (oracle.sql.ARRAY) rs.getObject("RATINGOBJ");

包含的 JDBC 库是 ojdbc6.jar (WEB_INF/lib)。所有库都包含在 war 文件中,并且服务器上没有设置“全局”库。我已验证应用程序中的任何位置均未包含其他 jdbc 库。

为了创建 JDBC 数据源,我为 ojdbc6.jar 创建了部署。这是我能想到的唯一可能的冲突来源。当我从 war 文件中删除 ojdbc6.jar 时,我得到一个 ClassNotFound 异常来代替 ClassCastException。

应用程序的所有其他部分都可以正常工作,除了这一行。我该如何进一步调试?

【问题讨论】:

  • 也许尝试运行一个非常简单的测试应用程序,只使用您的 JDBC 驱动程序作为依赖项?
  • 它只是偶尔发生吗?每次重新部署应用程序时是否都重新启动服务器?
  • 每次部署应用程序时,我都会重新启动服务器。我认为没有必要,但我还是这样做了。

标签: java oracle jboss classcastexception


【解决方案1】:

我不确定为什么从 web-inf/lib 加载不起作用。很可能类加载器是不同的。

执行前两个步骤进行诊断。之后尝试以下两种替代方法之一来解决问题。
1)通过比较rs.getObject().getClass('RATINGOBJ').getClassLoader()oracle.sql.ARRAY.class.getClassLoader()来检查类加载器是否相同 如果你在两个类加载器之间执行equals,它应该返回false,因为它看起来类加载器不同。 检查解释 ClassCastException when casting to the same class

这个问题早前已经在另一个论坛https://forums.oracle.com/message/9330314 上报告过了。在 jboss 中移动 jars 仍然会导致同样的问题。

2) 找出加载类的源 jar,然后删除不需要的 jar。 通过检查
rs.getObject().getClass('RATINGOBJ').getProtectionDomain().getCodeSource().getLocation() 找到两个不同类的 jar oracle.sql.ARRAY.class.getProtectionDomain().getCodeSource().getLocation() - Determine which JAR file a class is from

可能的解决方案:

a) 如果你需要这两个罐子,你必须移动罐子 rs.getObject().getClass('RATINGOBJ').getProtectionDomain().getCodeSource().getLocation()

并按照http://www.javaworld.com/community/node/8184 的规定创建模块。

b) 如果您仍然无法按预期加载类,请在 jboss 服务器库中指定库。

c) 强制从特定 jar 加载类的最后一个解决方案是在 bootclasspath 中指定 jar。

【讨论】:

  • ******* Object classloader = ModuleClassLoader for Module "deployment.ojdbc5.jar:main" from Service Module Loader ******* Class classloader = ModuleClassLoader for Module "deployment.Dispatch.war:main" from Service Module Loader ******* Object jarLoc = vfs:/content/ojdbc5.jar ******* Class jarLoc = vfs:/content/Dispatch.war/WEB-INF/lib/ojdbc5.jar ********* Classloaders are different *********** 打印了您建议的值。类加载器似乎不同。服务器上有 2 个部署,用于创建数据源的 ojdbc5.jar 和包含 ojdbc5.jar 的应用程序本身
  • 我仍然无法找到 JBoss EAP 的服务器库。如果我从 WEB_INF/lib 中删除 ojdbc5.jar,我会得到 ClassNotFound,如果我包含它。它与我安装为用于创建数据源的模块的同一 jar 冲突。明天我将尝试测试您可能的解决方案。谢谢。
  • 我能够使用解决方案 A 解决此问题。使用 ojdbc6.jar 创建了一个模块。用它来定义驱动程序并创建数据源。还将 jboss-deployment-structure.xml 添加到应用程序战争中以引用此模块,而不是将其包含在 WEB-INF/lib 中。类加载器现在显示相同,并且现在一切似乎都运行良好。相当复杂的是,我是 JBoss 的新手,未能意识到来自 RedHat 的 JBoss EAP 6 和 JBoss AS 7 之间的区别。感谢您的所有意见。
【解决方案2】:

您不应该在 WEB-INF/lib 级别有任何 JDBC 驱动程序 JAR。 Java EE 应用服务器需要它们处于应用服务器级别。

将其移至默认服务器 /lib 目录,看看是否更好。

【讨论】:

  • 只有当您希望容器提供例如数据库连接池?如果您自己做所有事情,则不必这样做。
  • 确实如此,但为什么要使用应用服务器而使用连接池? Tomcat 现在就要求它,而 JBOSS servlet/JSP 引擎是 Tomcat 的一个分支。
  • 我同意。我认为这是一个 ClassLoader 的事情。
  • 应用程序中包含的 JDBC 驱动程序不用于连接池。我在 appserver 级别定义了一个用于该目的的连接池。我在应用程序中需要 ojdbc6.jar 的原因是使用 java.sql.ARRAY 对象。听起来对吗?
  • 看到这个答案后,我将 ojdbc6.jar 移至 JBOSS_HOME/standalone/lib 并将其从 war 文件中删除(并重新启动服务器)。结果 java.lang.NoClassDefFoundError: oracle/sql/ARRAY 当我将 ojdbc6.jar 作为 WEB-INF/lib 的一部分时,我收到较早的错误 java.lang.ClassCastException: oracle.sql.ARRAY cannot be cast to oracle.sql.ARRAY 而这一切都只是使用该包中的 ARRAY 类。我确信我在这里做的事情根本上是错误的
猜你喜欢
  • 2011-06-08
  • 1970-01-01
  • 2016-10-12
  • 2011-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-06
  • 2012-04-27
相关资源
最近更新 更多