You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从PDF提取XML并JAXB反序列化报错:Buffer already closed(OpenShift环境)

问题:OpenShift部署后JAXB反序列化报错“java.io.IOException: Buffer already closed”

本地IntelliJ运行正常,但部署到OpenShift集群的JAR包执行时,通过Apache PDFBox从PDF提取XML片段后,JAXB反序列化失败,报错java.io.IOException: Buffer already closed。

具体流程:从PDF中提取得到List<myObject>,后续通过JAXB完成反序列化,核心代码如下:

创建Unmarshaller的代码

try {
      JAXBContext context = JAXBContext.newInstance(typeClasse.getClass());
      Unmarshaller unmarshaller = context.createUnmarshaller();
      SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
      String xsdFilePath = getXSD();
      Schema schema = factory.newSchema(this.getClass().getResource("/" + xsdFilePath));
      unmarshaller.setSchema(schema);
      unmarshaller.setEventHandler(event -> false);
      return unmarshaller;
    } catch (JAXBException | SAXException e) {
      throw new UnmarshallException(e);
    }

其中typeClasse是反序列化的目标类,getXSD()返回资源文件夹中xsd目录下的根XSD文件路径(如"xsd/myparentXSD.xsd"),该XSD已引入同目录下其他XSD。

流式处理List的代码

myList.stream()
        .map(myObject -> unmarshallFichier(myObject, unmarshaller))
        .collect(Collectors.toList());

反序列化方法实现

try {
  StreamSource stream = new StreamSource(myObject);
  JAXBElement<?> jaxbElement = unmarshaller.unmarshal(stream, typeClasse.getClass());
  return (T) jaxbElement.getValue();
} catch (JAXBException e) {
  throw new UnmarshallException(e);
}

排查方向与解决方案

1. Unmarshaller线程安全问题

JAXB的Unmarshaller实例不是线程安全的,流式处理stream().map(...)在OpenShift环境可能默认启用并行执行,多个线程共用同一个Unmarshaller会导致资源(Buffer)被提前关闭的冲突,本地环境可能因单线程执行未触发问题。

  • 解决方案:在map方法内部每次创建新的Unmarshaller实例,或者显式指定串行流(stream().sequential().map(...)),规范做法是避免复用Unmarshaller。

2. 类加载器与XSD资源加载异常

OpenShift中JAR包的类加载器和本地IDE存在差异,this.getClass().getResource("/" + xsdFilePath)可能无法正确加载XSD依赖文件(XSD内部引入的同目录文件),间接导致Unmarshaller处理时Buffer异常。

  • 解决方案:
    • 改用getResourceAsStream加载XSD,或使用SchemaFactory.newSchema(Source[])显式传入所有依赖的XSD Source,避免依赖自动加载;
    • 确认Maven/Gradle打包配置,确保src/main/resources/xsd下的所有XSD文件都被正确打入JAR包。

3. PDFBox提取的流提前关闭

从PDF提取的myObject如果是InputStream类型,OpenShift环境中PDFBox的资源管理可能更严格,导致流被隐式关闭,反序列化时流已不可用。

  • 解决方案:
    • 提取XML片段时,将流内容复制到内存(如ByteArrayInputStream),再传入反序列化方法,避免直接使用PDFBox返回的原始流;
    • 检查PDFBox代码,确保提取XML片段后流未被提前关闭。

内容的提问来源于stack exchange,提问作者Broshet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 09:05:33