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

javax.xml.parsers.FactoryFinder$ClassLoaderFinder ignores its own ClassLoader

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P3 P3
    • None
    • 1.4.1
    • xml
    • x86
    • windows_2000

      Name: gm110360 Date: 02/05/2002


      FULL PRODUCT VERSION :
      java version "1.3.1_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_01)
      Java HotSpot(TM) Client VM (build 1.3.1_01, mixed mode)

      FULL OPERATING SYSTEM VERSION : Microsoft Windows 2000
      [Version 5.00.2195]




      EXTRA RELEVANT SYSTEM CONFIGURATION :
      I don't know how the choices in the dropdowns for "Product
      Version" and "Subcategory" are helpful. According to the
      information in the MANIFEST.MF of my JAXP.JAR, I'm using
      Sepcification-Version 1.1 of jaxp.jar and Implementation-
      Version 1.1.1 of javax.xml.parsers.

      A DESCRIPTION OF THE PROBLEM :
      I am writing a class which will launch the Jakarta build
      tool ANT. This class includes a custom ClassLoader as an
      inner class, and this ClassLoader provides the necessary
      data to load all the classes ANT needs. In particular,
      this ClassLoader knows the location of jaxp.jar and
      crimson.jar. Crimson.jar contains the specific
      SAXParserFactory implementation ANT needs.

      The problem arises when the ANT code invokes
      javax.xml.parsers.SAXParserFactory.newInstance(). By
      viewing output from my custom ClassLoader, I see that
      javax.xml.parsers.FactoryFinder uses its own custom
      ClassLoader which does NOT delegate to my custom
      ClassLoader. Thus javax.xml.parsers.FactoryFinder has no
      knowledge about where crimson.jar is located, and I get a
      FactoryConfigurationError.

      My request is that
      javax.xml.parsers.FactoryFinder$ClassLoaderFinder be
      modified so that the custom ClassLoader it uses delegates
      to the ClassLoader which loaded
      javax.xml.parsers.FactoryFinder in the first place.



      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      I've created a small test case which exposes this issue. I
      will send a jar containing the test case once I know who to
      send it to. When you have the Test.jar, then
      1. Extract 'Test.jar' to some working directory.
      2. Make sure your %CLASSPATH% contains only '.'
      3. 'java Test'

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Expected Results: The final line of text output is the
      message: 'Invoked 'testMethod' and received object
      <SAXParserFacotry.toString()>', and no errors are reported.

      Actual Results: After a few debugging-style printlns
      appear, we see the message: 'This friendly error message is
      brought to you by 'Test.java', followed by the error output
      given below.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      java.lang.reflect.InvocationTargetException:
      javax.xml.parsers.FactoryConfigurationError: Provider
      org.apache.crimson.jaxp.SAXParserFactoryImpl not found
      at javax.xml.parsers.SAXParserFactory.newInstance
      (SAXParserFactory.java:105)
      at ParserCaller.testMethod(ParserCaller.java:12)
      at java.lang.reflect.Method.invoke(Native Method)
      at Test.run(Test.java:47)
      at Test.main(Test.java:16)

      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      As noted above, I have a small test, but it includes classes in two different
      directories and two jar files. I believe it would be easier for me to archive
      the whole test and send the archive to someone, rather than to attempt to paste
      source code here and explain how to assemble things.
      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      I do not know of a workaround for this issue.
      (Review ID: 138771)
      ======================================================================
      ###@###.### 11/2/04 21:58 GMT
      ===================

      Access Manager/Portal is also encountering the same issue with jdk 1.5.
      jdk's 1.5 rt.jar bundles "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl" class

      Sequence for the failure case:
      -------------------------------
      1)) Access Manager does quite a bit of XML parsing and hence we include "/usr/share/lib/xercesImpl.jar" (which bundles "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl" class)
       via the "classpathsuffix" in Sun Web Server's server.xml. This is the one from JES shared component.
          
      2) Since server.xml is modified we restart the server and things all work fine i.e., Access Manager parses XML files.
          
      3) We/Portal deploys a web application (.war file) using wdeploy command,
      Web application gets deployed successfully (and we do not stop and start the web server).
      Access Manager also works fine until it gets the first XML document to parse.
      On receiving the first XML document, we get the following exception in Access Manager debug logs:

         javax.xml.parsers.FactoryConfigurationError: Provider com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl not found
              at javax.xml.parsers.DocumentBuilderFactory.newInstance(DocumentBuilderFactory.java:104)
              at com.sun.identity.sm.SMSSchema.getXMLDocument(SMSSchema.java:365)
              at com.sun.identity.sm.ServiceSchemaManagerImpl.update(ServiceSchemaManagerImpl.java:360)
              at com.sun.identity.sm.ServiceSchemaManagerImpl.updateAndNotifyListeners(ServiceSchemaManagerImpl.java:338)

      Also we get 'CL LifeCycle stopped' in web server logs whenever this DocumentBuilderFactory class is trying to get instantiated.

      The java code that gets the new instance of DocumentBuilderFactory is:
              DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
       
      On further testing, we found that this happens only with JDK 1.5.

      Did some research on the web and noticed that the old classloader may not have been properly destroyed or set to null or the reference to the old classloader is not being properly destroyed.
      Discussed with Web Server engineer (Arvind Srinivas).
      As per the Web Server engineer's investigation/comments, checked the entire Access Manager codebase and there is no explicit contextclassloader setting for any Thread.
      (There is no Thread.currentThread().setContextClassLoader(..) in AM code).
      There is only the getContextClassLoader. I have commented that code too and tried the above scenerio. Still it fails with DocumentBuilderFactoryImpl class not found whenever a web application is deployed with wdeploy in Sun Web Server ( no restart of web server) and whenever the DocumentBuilderFactory.newInstance() is called.
       
       ./com/sun/identity/log/Logger.java
                  //////sujatha clz = Thread.currentThread().getContextClassLoader().loadClass(formatterClass);
      The stack trace from Sun Web Server errors logs are given below.

      javax.xml.parsers.SecuritySupport.getResourceAsStream(SecuritySupport.java:65)
      : CORE3283: stderr: at
      javax.xml.parsers.FactoryFinder.findJarServiceProvider(FactoryFinder.java:213)
      : CORE3283: stderr: at
      javax.xml.parsers.FactoryFinder.find(FactoryFinder.java:185)
      : CORE3283: stderr: at
      javax.xml.parsers.DocumentBuilderFactory.newInstance(DocumentBuilderFactory.java:98)

      Went through the DocumentBuilderFactory source code and got the author's name and spoke to jeff (SUTTOR, JEFFREY). Explained to him and as per his suggestion, adding this description and moving the P4 to P3 (RFE to Bug). He mentioned there is a fix available for apache xerces 2.x version.

      Fix/Suggestion is badly needed as i am working on a P1 Portal issue (bugid : 6334633) which depends on Access manager and they are going IFR in December 2005.
      Also these bugs have been filed for the same behaviour.
      bugids :
      6334366
      6330501
      6330502
      So pls. look into this.
      thx,
      -Sujatha.
      I looked at the corresponding lines as printed by log. Per these log statements JAPX classes part of JDK 1.5 are being used. Per the log statement it seems this bug is different from the original bug report. Because Thread context class loader is indeed available. Note that even if its not set, there is one associated with it unless it is explicity set to null. This can be checked by printing Thread.currentThread().getContextClassLoader(). The context class loader of the primordial thread is typically set to class loader used to load the application.

      So whatever class loader is used to load the application and then JAXP classes is not able to find "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl". If there is a particular class
      loader supplied which loads said application , please ensure that class loader knows where to find "com.sun.org....jaxp.DocumentBuilderFactoryImpl" class.

      If this step fails, next step JAXP parser does is that , it tries to load the class using the class loader which loaded javax.xml.parsers.DocumentBuilderFactory and then javax.xml.parsers.FactoryFinder.

      Hope this information would be useful for you to debug further . Let us know if you need more information. I work from IEC (Bangalore), if you need to speak to me, you can call me any time b/w 8:30 AM to 10:00 PM. (IST) at my ext. 87425. Let me know in advance and i will forward my ext. to my mobile.

            nbajajsunw Neeraj Bajaj (Inactive)
            gmanwanisunw Girish Manwani (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: