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

javax.swing.text.html.HTMLEditorKit.Parser.parse() is not thread safe

XMLWordPrintable

      PLATFORM:
      Windows XP. Reproducible with JDK 5 and JDK 6.

      DESCRIPTION from Licensee/CU:
      A full description and readme for the testcases has been attached to the CR.
      This Description is a summary of that readme file.

      We use the standard HTML parser and encounter some errors from time to time.
      Each thread in our testcase parses one of two files - either component.html or
      list.html. When a list tag is encountered while reading component.html, or a
      component tag is encountered while reading list.html, an error is reported
      using LOG4J and a counter is incremented.

      At the end of the test, we report the total number of files parsed by each thread, and the number of parsing errors. The errors we see seem to be caused by concurrency problems, despite the statement in the API documentation that the parse() method should be thread safe:

      http://java.sun.com/javase/6/docs/api/javax/swing/text/html/HTMLEditorKit.Parser.html

      A suggested fix is included below.

      RECREATION INSTRUCTIONS:

      The testcase package contains the source code of the testcase as an Eclipse
      project. However, there is also an ANT script to run all tests from a shell.
      To run it from command prompt you require ANT 1.7.0. You also need to set the
      following command line options:

        set ANT_HOME=c:\ant
        set JAVA_HOME=c:\jdk-1.5.0.05
        set PATH=%PATH%;%ANT_HOME%\bin

      Then cd to the working directory (i.e where the testcase is) to run the testcases. You can run each test individually with the respective ANT target:

        ant testStandardParser
        ant testPatchedParser

      or you can run "ant all" to execute both tests in turn.

      The ant target testStandardParser encounters many errors even with a small number of threads - 5 in total, with the odd numbers parsing component.html and the even numbers parsing list.html.

      The ant target testPatchedParser runs the testcase with some modified classes (see SUGGESTED FIX section below, and the readme in the testcase package for details).

      The results of running the tests should look something like this, with the testStandardParser producing multiple errors, and testPatchedParser working cleanly:

      testStandardParser results (failures marked with "-->"):

           [echo] ******************************************************
           [echo] * STANDARD PARSER *
           [echo] ******************************************************
           [java] INFO [main] - LOG4J initialized with /C:/TEMP/ProblemParser/properties/log4j.properties (reload configuration every 15 seconds).
           [java] INFO [main] - Testing.
           [java] INFO [main] - Using standard JDK HTML parser.
           [java] INFO [main] - Launching 6 threads.
           [java] INFO [main] - Duration:10 sec
           [java] INFO [Thread<0>] - StartedThread<0>
           [java] INFO [Thread<1>] - StartedThread<1>
           [java] INFO [Thread<3>] - StartedThread<3>
           [java] INFO [Thread<2>] - StartedThread<2>
           [java] INFO [main] - Waiting 10 sec before stopping the test.
           [java] INFO [Thread<5>] - StartedThread<5>
           [java] INFO [Thread<4>] - StartedThread<4>
           [java] ERROR [Thread<0>] - Tag list in file component.html.
           [java] ERROR [Thread<1>] - Tag component in file list.html.
           [java] ERROR [Thread<2>] - Tag list in file component.html.
           [java] ERROR [Thread<2>] - Tag list in file component.html.
           [java] ERROR [Thread<4>] - Tag list in file component.html.
           [java] ERROR [Thread<1>] - Tag component in file list.html.
           [java] ERROR [Thread<0>] - Tag list in file component.html.
           [java] ERROR [Thread<3>] - Tag component in file list.html.
           [java] ERROR [Thread<2>] - Tag list in file component.html.
           [java] ERROR [Thread<1>] - Tag component in file list.html.
           [java] ERROR [Thread<5>] - Tag component in file list.html.
      ¿
           [java] ERROR [Thread<0>] - Tag list in file component.html.
           [java] ERROR [Thread<3>] - Tag component in file list.html.
           [java] ERROR [Thread<4>] - Tag list in file component.html.
           [java] ERROR [Thread<0>] - Tag list in file component.html.
           [java] ERROR [Thread<0>] - Tag list in file component.html.
           [java] ERROR [Thread<1>] - Tag component in file list.html.
           [java] INFO [main] - Waiting for termination of Thread<0>
           [java] INFO [Thread<4>] - Stopped Thread<4>
           [java] INFO [Thread<5>] - Stopped Thread<5>
           [java] INFO [Thread<3>] - Stopped Thread<3>
           [java] INFO [Thread<0>] - Stopped Thread<0>
           [java] INFO [Thread<1>] - Stopped Thread<1>
           [java] INFO [main] - Waiting for termination of Thread<1>
           [java] INFO [main] - Waiting for termination of Thread<2>
           [java] INFO [Thread<2>] - Stopped Thread<2>
           [java] INFO [main] - Waiting for termination of Thread<3>
           [java] INFO [main] - Waiting for termination of Thread<4>
           [java] INFO [main] - Waiting for termination of Thread<5>
      --> [java] ERROR [main] - Count: 2609 Fail: 119 Thread<0>
      --> [java] ERROR [main] - Count: 2686 Fail: 120 Thread<1>
      --> [java] ERROR [main] - Count: 2606 Fail: 114 Thread<2>
      --> [java] ERROR [main] - Count: 2714 Fail: 114 Thread<3>
      --> [java] ERROR [main] - Count: 2606 Fail: 98 Thread<4>
      --> [java] ERROR [main] - Count: 2727 Fail: 117 Thread<5>
           [java] INFO [main] - Existing.
           [java] INFO [main] - Done.

      testPatchedParser results:

           [echo] ******************************************************
           [echo] * PATCHED PARSER *
           [echo] ******************************************************
           [java] INFO [main] - LOG4J initialized with /C:/TEMP/ProblemParser/properties/log4j.properties (reload configurati
      on every 15 seconds).
           [java] INFO [main] - Testing.
           [java] INFO [main] - Using patched parser with clone.
           [java] INFO [main] - Launching 6 threads.
           [java] INFO [main] - Duration:10 sec
           [java] INFO [Thread<0>] - StartedThread<0>
           [java] INFO [main] - Waiting 10 sec before stopping the test.
           [java] INFO [Thread<1>] - StartedThread<1>
           [java] INFO [Thread<2>] - StartedThread<2>
           [java] INFO [Thread<4>] - StartedThread<4>
           [java] INFO [Thread<3>] - StartedThread<3>
           [java] INFO [Thread<5>] - StartedThread<5>
           [java] INFO [main] - Waiting for termination of Thread<0>
           [java] INFO [Thread<0>] - Stopped Thread<0>
           [java] INFO [main] - Waiting for termination of Thread<1>
           [java] INFO [Thread<4>] - Stopped Thread<4>
           [java] INFO [Thread<3>] - Stopped Thread<3>
           [java] INFO [Thread<5>] - Stopped Thread<5>
           [java] INFO [Thread<1>] - Stopped Thread<1>
           [java] INFO [main] - Waiting for termination of Thread<2>
           [java] INFO [Thread<2>] - Stopped Thread<2>
           [java] INFO [main] - Waiting for termination of Thread<3>
           [java] INFO [main] - Waiting for termination of Thread<4>
           [java] INFO [main] - Waiting for termination of Thread<5>
           [java] INFO [main] - Count: 2447 Thread<0>
           [java] INFO [main] - Count: 2477 Thread<1>
           [java] INFO [main] - Count: 2428 Thread<2>
           [java] INFO [main] - Count: 2494 Thread<3>
           [java] INFO [main] - Count: 2409 Thread<4>
           [java] INFO [main] - Count: 2512 Thread<5>
           [java] INFO [main] - Existing.
           [java] INFO [main] - Done

      SUGGESTED FIX:

      The problem does not occur if we make the following modifications in the class library code:

      Element.java
      ------------

      Class declaration modified to:

          class Element implements DTDConstants, Serializable, Cloneable {
                                                               ^^^^^^^^^
      And added clone() implementation:

          protected java.lang.Object clone() {
              try {
                  return super.clone();
              } catch (CloneNotSupportedException e) {
                  e.printStackTrace();
                  throw new Error("ne doit pas arriver");
              }
          }

      Parser.java
      -----------

      Changed elem = dtd.getElement("unknown");
      to elem = (Element)(dtd.getElement("unknown")).clone;
                                                                                 Changed elem = dtd.getElement("unknown");
      to elem = (Element)(dtd.getElement("unknown")).clone;

            peterz Peter Zhelezniakov
            dkorbel David Korbel (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: