【问题标题】:Oracle JVM runtime error: Provider com.sun.xml.stream.ZephyrParserFactory not foundOracle JVM 运行时错误:未找到提供程序 com.sun.xml.stream.ZephyrParserFactory
【发布时间】:2016-09-06 17:49:06
【问题描述】:

背景:

我们有一个 Oracle 11g 数据库,它运行 JRE 版本 1.6.0_43 的 Java 虚拟机。我们的用户界面托管在 Apache 网络服务器上,该服务器通过 mod-plsql 与数据库连接。

我们有一些 PLSQL 过程调用存储在数据库中 Java 源中的 Java 过程 - 一个例子是我们用来生成 XLS 文件的 Java 过程。

我们之前一直使用 Apache POI 套件 3.8 版使用 DOM Parser 从 XML 生成 XLS 文件,但我们已经升级到 POI 3.9,以便我们可以使用 Streaming XSSF Workbook 类来有效地生成 XLSX 文件( SXSSF 在 POI 3.8 中可用,但核心过程 dispose() 直到 POI 3.9 才可用。

另外,出于效率原因,我们在生成 XLSX 文件时使用 StAX 解析 (XMLStreamReader),而不是我们用于生成 XLS 的更占用内存的 DOM Parser 方法。

要将我们数据库中的 Java POI 3.8 升级到 3.9,我们有两个步骤:

1) 在包含 POI 3.8 套件的 jar 上运行 dropjava:

dropjava -user=xxxxxx@xxxxxx poi-3.8-20120326.jar poi-examples-3.8-20120326.jar poi-excelant-3.8-20120326.jar poi-ooxml-3.8-20120326.jar poi-ooxml-schemas-3.8-20120326.jar poi-scratchpad-3.8-20120326.jar lib\commons-logging-1.1.jar lib\junit-3.8.1.jar lib\log4j-1.2.13.jar ooxml-lib\dom4j-1.6.1.jar ooxml-lib\stax-api-1.0.1.jar ooxml-lib\xmlbeans-2.3.0.jar

2) 然后我们运行 loadjava 命令来安装 3.9 套件:

loadjava -user=xxxxxx@xxxxxx -genmissing -resolve -force poi-3.9-20121203.jar poi-examples-3.9-20121203.jar poi-excelant-3.9-20121203.jar poi-ooxml-3.9-20121203.jar poi-ooxml-schemas-3.9-20121203.jar poi-scratchpad-3.9-20121203.jar lib\commons-logging-1.1.jar lib\junit-3.8.1.jar lib\log4j-1.2.13.jar ooxml-lib\dom4j-1.6.1.jar ooxml-lib\stax-api-1.0.1.jar ooxml-lib\xmlbeans-2.3.0.jar

XLSX 一代一开始根本不工作;我们在运行时在 Java 中收到了这个异常:

java.lang.ClassCastException

我们没有确认是哪个特定的类导致了问题,但我们注意到,在安装 POI 3.9(包括 StAX stax-api-1.0.1 jar)后,我们的 Java 类库中的数据库。具体来说,这些类及其路径是重复的(并被导入到我们生成 xlsx 的 Java 源中):

import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;

考虑到重复项可能导致异常,我们删除了 StAX 解析器 jar(StAX 套件在我们的 Java 版本之前的某个时间点“折叠”到核心 JDK,因此可能不需要导入StAX jar 包含在 POI 3.9 中):

dropjava -user=xxxxxx@xxxxxx ooxml-lib\stax-api-1.0.1.jar

这删除了重复的类并解决了 ClassCastException,即它不再发生。但是有一个新问题。

问题:

新的 XLSX 方法现在在运行时间歇性地失败并出现以下错误:

javax.xml.stream.FactoryFinder$ConfigurationError: Provider com.sun.xml.stream.ZephyrParserFactory not found

有问题的类 com.sun.xml.stream.ZephyrParserFactory, 似乎已正确安装在我们的数据库中。我们已经在一个单独的平台上进行了一些测试,我们发现删除该类完全破坏了我们的解析,即我们确信该类已安装在我们的实时平台上,因为我们的代码大部分时间都可以工作,但无法正常工作未安装类的时间。

该错误大约每 10 次左右 XLSX 生成尝试就会发生一次(我们每次都使用不同的文件和同一个文件进行测试 - XML 的内容是什么似乎并不重要)。这行代码会产生错误:

XMLInputFactory factory = XMLInputFactory.newInstance();    

通过一些调查,我们发现是否发生错误取决于哪个 Oracle 会话正在处理 Web 服务器接收到的初始 HTTP 请求。 我觉得这里真正的问题是,是什么导致只有某些 Oracle 会话无法以提供者的身份访问 Zephyr 类并产生错误?任何想法都将不胜感激。

【问题讨论】:

    标签: java plsql oracle11g jvm stax


    【解决方案1】:

    基于:

    how to override a service provider in java

    https://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/SJSXP4.html

    您可以为 javax.xml.stream.XMLInputFactory 设置系统属性,以指定用于在运行时创建 XMLInputFactory 的实现实例的实现类。

    我们的 db 类库中存储的核心 Java API 中有这样一个可用的实现类:

    XMLInputFactoryImpl
    

    我们现在在 Java 过程的开头使用这样的一行来设置该 Oracle 会话期间的系统属性:

    System.setProperty("javax.xml.stream.XMLInputFactory", "<class path>XMLInputFactoryImpl");
    

    这似乎解决了我们的一些 Oracle 会话在运行时遇到的 XMLInputFactory 服务提供者混乱。

    【讨论】:

      【解决方案2】:

      这可能与此处描述的CDATA events 的处理有关http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/SJSXP5.html

      根据输入文件触发或不触发此事件。如果事件被抛出,你会得到Provider com.sun.xml.stream.ZephyrParserFactory not found 错误。

      您需要调查哪些代码试图实例化这个具体的服务提供者。

      通常,实现特定接口的服务提供者在 Jar 文件内的目录META-INF/services 中声明。在此处找到提供a simple service-provider loading facilityServiceLoader 的描述

      【讨论】:

      • 请注意,我们一直在通过每次将相同的 XML 传递给 Java 过程进行测试,XML 总是包含 CDATA 单元格/事件,并且每次都由XMLInputFactory factory = XMLInputFactory.newInstance(); 行生成错误确实发生,而不是在读取 XML 时遇到 CDATA 事件时生成。我不确定这些警告是否会排除您建议的确切原因;也许你知道。无论哪种方式,这对我来说都是一条很有希望的路线。非常感谢您的回答。
      • @MrC 好的。不知道它使用相同的输入文件失败。您的类路径中是否有sjsxp.jar(还要检查 manifest.mf 中的类路径)?我相信您应该删除它,因为 JSR 173 是 Java 6 的一部分。
      • 我们没有在系统属性中为 java.class.path 设置任何东西,也就是说,从技术上讲,我们没有/使用类路径。相反,我们使用 loadjava 命令将我们需要的类加载到数据库 Java 类库中。但是,我们确实对 java.library.path 系统属性进行了设置; sjsxp.jar 没有出现在那个目录中它看起来确实有许多其他的罐子多年来仍然在那里。我现在想知道这些 jar 中的任何一个是否会导致冲突有时,即某些 Oracle 会话访问 Java 库路径而不是 db Java 类库。
      • @MrC 根据我的分析,您应该搜索包含文件 META-INF/services/javax.xml.stream.XMLEventFactory 的 Jar 文件。然后检查该文件是否包含行com.sun.xml.stream.ZephyrParserFactory。在您的情况下(因为 JEE5 和 Java 6 支持 JSR173)从类路径中删除这个 Jar 文件应该是安全的。 一如既往。之前做好备份。 ;-)
      猜你喜欢
      • 2013-12-15
      • 1970-01-01
      • 2021-12-15
      • 1970-01-01
      • 2014-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多