0

We are using Child first classloader to avoid jar conflicts and load the classes from a particular path. With the service loader and the xml-apis jar in the child classloader's classpath, we are facing issues.

xerces2 jars service loader creates an object of javax.xml.parsers.DocumentBuilderFactory with org.apache.xerces.jaxp.DocumentBuilderFactoryImpl if DocumentBuilderFactoryImpl not present in the classpath, It loads the fallback class present in the rt.jar. Under normal circumstances, the code works fine.

With using child first classloader on top of System classloader, we facing issues in the following lines.

 DocumentBuilderFactory newInstance()

the above line is used for creating the object. The method details are,

public static DocumentBuilderFactory newInstance() {
    return (DocumentBuilderFactory)FactoryFinder.find(DocumentBuilderFactory.class, "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
}

The first argument to the find method,

DocumentBuilderFactory.class

creates a class object for javax.xml.parsers.DocumentBuilderFactory class. but even we have set the classloader with child classloader, .class operator loads the class with System classloader and creates a class object, not with the current child classloader on top

.

Inside the service loader, creates an object for org.apache.xerces.jaxp.DocumentBuilderFactoryImpl with child classloader and the child first classloader loads the javax.xml.parsers.DocumentBuilderFactory class.

As the DocumentBuilderFactory.class loaded in the system classloader and the org.apache.xerces.jaxp.DocumentBuilderFactoryImpl class loaded in the top child classloaders are not assignable to each other as both javax.xml.parsers.DocumentBuilderFactory is created in separate classloaders.

My question is,

Is there any way to avoid the DocumentBuilder.class from loading to the system classloader?

For child first classloader we are using the following library https://github.com/kamranzafar/JCL/

aravinth
  • 416
  • 1
  • 5
  • 20
  • Is it your code that’s calling DocumentBuilderFactory.newInstance? If so, you can call the other newInstance method which takes a ClassLoader as an argument. – VGR Apr 05 '20 at 04:34
  • Even If we pass the classloader as an argument, It won't work. In this method, the argument DocumentBuilderFactory.class is passed by default. It creates an object with system classloaders causing the issue. The passed classloader is used for creating service implementation objects. public static DocumentBuilderFactory newInstance(String factoryClassName, ClassLoader classLoader) { return (DocumentBuilderFactory)FactoryFinder.newInstance(DocumentBuilderFactory.class, factoryClassName, classLoader, false); } – aravinth Apr 05 '20 at 04:41
  • You could just create an instance of `org.apache.xerces.jaxp.DocumentBuilderFactoryImpl` directly, instead of calling `DocumentBuilderFactory.newInstance()` to figure it out from context. – Andreas Apr 05 '20 at 05:55
  • 1
    @Andreas I'm not calling DocumentBuilderFactory.newInstance(). There are libraries that using XML parsers underneath calling them. I can't modify on there. – aravinth Apr 05 '20 at 05:59

0 Answers0