5

LinuxマシンでいくつかのXMLファイルを解析するために標準のjavax.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
4

1 に答える 1

2

同時スレッドの問題のようです。

エラーは、表示されたコードレットの外側のどこかにある可能性があります。しかし、DocumentBuilderFactory と XPathFactory についても、それらがスレッドセーフかどうかはわかりません。ドキュメントには記載されていません。

synchronized {}最初のテストとして、XML ファイルを解析するためのコード全体を句に入れることをお勧めします。これで問題が解決する場合、それは間違いなくマルチスレッドの問題です。この場合、同期する必要があるコードの最小部分を見つける必要があります。

于 2012-04-24T16:08:46.287 に答える