Java中使用javax.xml出现“Bad File Descriptor IOException”的错误

5

我正在使用标准的javax.xml包在Linux机器上解析一些XML文件。我的代码如下:

try 
{
    // Prepare parser
    DocumentBuilder documentBuilder = documentBuilderFactory
        .newDocumentBuilder();
    Document document = documentBuilder.parse(file.getAbsolutePath()); // This is line 397
    XPath xPath = xPathFactory.newXPath();
    ...
}
catch(IOException e) { ... }

一个DocumentBuilderFactory可以被多个线程访问,同样一个XPathFactory也是如此,我认为这是可以接受的使用方式。当使用上述代码解析XML文件时,有时会出现以下错误。

java.io.IOException: Bad file descriptor
        at java.io.FileInputStream.readBytes(Native Method)
        at java.io.FileInputStream.read(FileInputStream.java:229)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:229)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:246)
        at org.apache.xerces.impl.XMLEntityManager$RewindableInputStream.read(Unknown Source)
        at org.apache.xerces.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
        at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
        at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
        at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
        at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
        at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
        at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
        at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
        at mypackage.MyXmlParser.parseFile(MyXmlParser.java:397)
        at mypackage.MyXmlParser.access$500(MyXmlParser.java:51)
        at mypackage.MyXmlParser$1.call(MyXmlParser.java:337)
        at mypackage.MyXmlParser$1.call(MyXmlParser.java:328)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:284)
        at java.util.concurrent.FutureTask.run(FutureTask.java:138)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:665)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:690)
        at java.lang.Thread.run(Thread.java:799)

我偶尔(约10%的时间)会看到以下额外文本:

Caused by:
java.io.IOException: Bad file descriptor
        at org.apache.xml.serializer.ToStream.flushWriter(ToStream.java:260)
        at org.apache.xml.serializer.ToXMLStream.endDocument(ToXMLStream.java:191)
        at org.apache.xalan.transformer.TransformerIdentityImpl.endDocument(TransformerIdentityImpl.java:983)
        at org.apache.xml.serializer.TreeWalker.traverse(TreeWalker.java:174)
        at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:410)
        ... 9 more

当我手动检查这些文件时,我发现无法区分哪些文件是失败的,哪些文件是成功的。我可以确认成功的文件是有效的XML文件,没有特殊字符或过早结束。

有没有人知道为什么会出现这种情况,以及我该如何避免它?

> java -version
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build pxa64dev-20061002a (SR3) )
IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Linux amd64-64 j9vmxa6423-20061001 (JIT enabled)
J9VM - 20060915_08260_LHdSMr
JIT  - 20060908_1811_r8
GC   - 20060906_AA)
JCL  - 20061002

2
似乎在数据读取开始之前,您的FileStream已被关闭。您可能需要调查为什么它被关闭了。 - kosa
谢谢,如果是这样的话,我找不到任何原因。除了我上面发布的 javax.xml 代码之外,我没有触碰任何文件。 - Ina
1个回答

1

看起来是并发线程的问题。

错误可能出现在您展示给我们的代码块之外。但是对于DocumentBuilderFactory和XPathFactory,我不确定它们是否线程安全;文档中没有提到。

首先建议您将解析XML文件的整个代码放入synchronized {}子句中进行测试。如果这解决了您的问题,那么它肯定是一个多线程问题。在这种情况下,您必须找出必须同步的最小代码部分。


似乎解决了,谢谢。DocumentBuilderFactory 和 XPathFactory 显然不是线程安全的。 - Ina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接