Short version
If you came across a ClassNotFoundException
in your logs or in the Jenkins UI about the class com.sun.xml.internal.bind.v2.ContextFactory
, then you can solve this problem by adding a system property to your instance.
Edit the Jenkins launcher and add -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory
in the JAVA_OPTS
.
Long version
Problem
Some Jenkins plugins are using JAXB to deserialize configuration, reports or exchanges with external services.
When running Jenkins on Java 11, it is still possible to see this stack trace in the logs:
hudson.remoting.ProxyException: java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory at jenkins.util.AntClassLoader.findClassInComponents(AntClassLoader.java:1374) at jenkins.util.AntClassLoader.findClass(AntClassLoader.java:1327) at jenkins.util.AntClassLoader.loadClass(AntClassLoader.java:1080) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) at java.xml.bind/javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:122) at java.xml.bind/javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:155) at java.xml.bind/javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:276) Caused: hudson.remoting.ProxyException: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
This kind of exception was reported on JENKINS-55202 - Performance Signature Plugin: JAXB API is missing with Java 11 Closed for example.
The ContextFactory
implementation is not existing in the library offered by the JAXB plugin. It's in fact a fallback implementation, which is not in the libraries.
What is happening is that JAXB requires a context, which is nonexistant. To create it, JAXB is looking for a context factory implementation. Without any configuration, it will try to use com.sun.xml.internal.bind.v2.ContextFactory
.
Solution
It is possible to configure JAXB to use a context factory implementation existing in the classpath.
To do so, we can define a system property to locate the implementation. The name of the system property must be javax.xml.bind.JAXBContextFactory
and the value can differ depending on the libraries available. It is possible to use com.sun.xml.bind.v2.ContextFactory
which is provided by the JAXB library and JAXB plugin.
This is possible, as long as the plugin is not explicitly using the ClassLoader
to access those classes. If not, you need to see java9.wtf/class-loading and use the ClassLoader.getPlatformClassLoader
method to have access to the javax.xml.bind
package.