Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8179941

Two threads cannot use XPathExpressions from different XPathFactories

XMLWordPrintable

      FULL PRODUCT VERSION :
      java version "1.8.0_131"
      Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
      Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.39-1+deb8u2 (2017-03-07) x86_64 GNU/Linux


      A DESCRIPTION OF THE PROBLEM :
      The XPathExpression implementation shipped with de JDK uses static variables to save state. Even if two threads use their own XPathFactory, obtained using synchronized calls to XPathFactory.newInstance(), exceptions occur if they call evaluate(InputSource) on an XPathExpression created by their own XPathFactory.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Create two threads each with their own XPathFactory. Let them evaluate correctly formed XPathExpressions on a valid source.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The two threads should be able to evaluate the XPathExpression without exceptions.
      ACTUAL -
      Exceptions occur at random. I have encountered SAXException and NullPointerException.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      org.xml.sax.SAXException: FWK005 parse may not be called while parsing.
      at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
      at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
      at org.apache.xpath.jaxp.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:289)
      at org.apache.xpath.jaxp.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:319)
      at XPathTest$1.run(XPathTest.java:38)
      at java.lang.Thread.run(Thread.java:748)



      REPRODUCIBILITY :
      This bug can be reproduced often.

      ---------- BEGIN SOURCE ----------
      import java.io.StringReader;

      import javax.xml.xpath.XPathExpressionException;
      import javax.xml.xpath.XPathFactory;

      import org.xml.sax.InputSource;

      public class XPathTest {

          // This field is set to true as soon as one thread encounters an exception. When this happens, both threads will terminate.
          private static volatile boolean exception;

          private static Object lock = new Object();

          public static void main(String[] args) {
              Thread thread1 = createThread();
              Thread thread2 = createThread();
              thread1.start();
              thread2.start();
              try {
                  // wait at most two minutes
                  thread1.join(60000);
                  thread2.join(60000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }

          private static Thread createThread() {
              String xml = "<test/>";
              return new Thread(new Runnable() {
                  @Override
                  public void run() {
                      while (!exception) {
                          try {
                              XPathFactory xPathFactory;
                              // Synchronize both threads, as XPathFactory.newInstance() is not thread-safe.
                              synchronized (lock) {
                                  xPathFactory = XPathFactory.newInstance();
                              }
                              xPathFactory.newXPath().compile("/test").evaluate(new InputSource(new StringReader(xml)));
                          } catch (XPathExpressionException e) {
                              e.printStackTrace();
                              exception = true;
                          }
                      }
                  }
              });

          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Create a synchronized method that handles every xpath evaluation in the application.

            joehw Joe Wang
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: