Quarkus classLoader conflicts

Viewed 3471

I am facing an error while trying to build my quarkus app. It seems to be related to the fact that there are two class loaders that have different class objects for javax/xml/namespace/QName as it is noticed in this part of the stack-trace : Caused by: java.lang.LinkageError: loader constraint violation: when resolving field "DATETIME" the class loader (instance of io/quarkus/bootstrap/classloading/QuarkusClassLoader) of the referring class, javax/xml/datatype/DatatypeConstants, and the class loader (instance of <bootloader>) for the field's resolved type, javax/xml/namespace/QName, have different Class objects for that type . But I don't understand exactly what's going on and don't know how to solve it.

Can anyone help please ?

Here is the full stack-trace.

2020-07-21 11:25:18,432 ERROR [io.qua.run.boo.StartupActionImpl] (Quarkus Main Thread) Error running Quarkus: java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at io.quarkus.runner.bootstrap.StartupActionImpl$3.run(StartupActionImpl.java:144)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ExceptionInInitializerError
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.lang.Class.newInstance(Class.java:442)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:60)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:38)
        at io.quarkus.runtime.Quarkus.run(Quarkus.java:106)
        at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
        ... 6 more
Caused by: java.lang.RuntimeException: Failed to start quarkus
        at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:190)
        ... 15 more
Caused by: java.lang.RuntimeException: Failed to initialize Arc
        at io.quarkus.arc.Arc.initialize(Arc.java:26)
        at io.quarkus.arc.runtime.ArcRecorder.getContainer(ArcRecorder.java:35)
        at io.quarkus.deployment.steps.ArcProcessor$generateResources-1120260799.deploy_0(ArcProcessor$generateResources-1120260799.zig:72)
        at io.quarkus.deployment.steps.ArcProcessor$generateResources-1120260799.deploy(ArcProcessor$generateResources-1120260799.zig:36)
        at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:149)
        ... 15 more
Caused by: java.lang.LinkageError: loader constraint violation: when resolving field "DATETIME" the class loader (instance of io/quarkus/bootstrap/classloading/QuarkusClassLoader) of the referring class, javax/xml/datatype/DatatypeConstants, and the class loader (instance of <bootloader>) for the field's resolved type, javax/xml/namespace/QName, have different Class objects for that type
        at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl.<clinit>(RuntimeBuiltinLeafInfoImpl.java:254)
        at com.sun.xml.bind.v2.model.impl.RuntimeTypeInfoSetImpl.<init>(RuntimeTypeInfoSetImpl.java:33)
        at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.createTypeInfoSet(RuntimeModelBuilder.java:98)
        at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.createTypeInfoSet(RuntimeModelBuilder.java:54)
        at com.sun.xml.bind.v2.model.impl.ModelBuilder.<init>(ModelBuilder.java:132)
        at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.<init>(RuntimeModelBuilder.java:62)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:425)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:273)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:109)
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1126)
        at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:135)
        at com.sun.xml.bind.v2.JAXBContextFactory.createContext(JAXBContextFactory.java:35)
        at javax.xml.bind.ContextFinder.find(ContextFinder.java:393)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:691)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:632)
        at com.examlpe.middleware.DistributedContextWrapper.<clinit>(DistributedContextWrapper.java:32)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at com.exemple.quarkus.producers.RegisterProducers_ProducerMethod_distributedContextWrapperProducer_43b1afaa6d80f8d1886d6736d01bae86f45d5b94_Bean.<init>(RegisterProducers_ProducerMethod_distributedContextWrapperProducer_43b1afaa6d80f8d1886d6736d01bae86f45d5b94_Bean.zig:44)
        at io.quarkus.arc.setup.Default_ComponentsProvider.addBeans2(Default_ComponentsProvider.zig:1115)
        at io.quarkus.arc.setup.Default_ComponentsProvider.getComponents(Default_ComponentsProvider.zig:43)
        at io.quarkus.arc.impl.ArcContainerImpl.<init>(ArcContainerImpl.java:106)
        at io.quarkus.arc.Arc.initialize(Arc.java:20)
        ... 19 more

2020-07-21 11:25:18,433 ERROR [io.qua.dep.dev.DevModeMain] (main) Failed to start Quarkus: java.lang.RuntimeException: java.lang.RuntimeException: Failed to initialize Arc
        at io.quarkus.dev.appstate.ApplicationStateNotification.waitForApplicationStart(ApplicationStateNotification.java:51)
        at io.quarkus.runner.bootstrap.StartupActionImpl.runMainClass(StartupActionImpl.java:155)
        at io.quarkus.deployment.dev.IsolatedDevModeMain.firstStart(IsolatedDevModeMain.java:95)
        at io.quarkus.deployment.dev.IsolatedDevModeMain.accept(IsolatedDevModeMain.java:301)
        at io.quarkus.deployment.dev.IsolatedDevModeMain.accept(IsolatedDevModeMain.java:42)
        at io.quarkus.bootstrap.app.CuratedApplication.runInCl(CuratedApplication.java:131)
        at io.quarkus.bootstrap.app.CuratedApplication.runInAugmentClassLoader(CuratedApplication.java:84)
        at io.quarkus.deployment.dev.DevModeMain.start(DevModeMain.java:126)
        at io.quarkus.deployment.dev.DevModeMain.main(DevModeMain.java:56)
Caused by: java.lang.RuntimeException: Failed to initialize Arc
        at io.quarkus.arc.Arc.initialize(Arc.java:26)
        at io.quarkus.arc.runtime.ArcRecorder.getContainer(ArcRecorder.java:35)
        at io.quarkus.deployment.steps.ArcProcessor$generateResources-1120260799.deploy_0(ArcProcessor$generateResources-1120260799.zig:72)
        at io.quarkus.deployment.steps.ArcProcessor$generateResources-1120260799.deploy(ArcProcessor$generateResources-1120260799.zig:36)
3 Answers

After further research in my dependencies by using the maven dependency tree tool I saw that the issue was due to the stax-api dependency. This dependency was transitively included in my project. Since then it was difficult to solve the problem because it was not directly included in my poms thus not visible. What I did was just to exclude that stax-api dependency from my pom and that has solved the problem.

Finaly the dependency will look like :

    <dependency>
      <groupId>com.example.lib</groupId>
      <artifactId>my-lib</artifactId>
      <version>${example-lib-version}</version>
      <exclusions>
        <exclusion>
          <groupId>stax</groupId>
          <artifactId>stax-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

With com.example.lib:my-lib the dependency through which stax api was included.

This problem is actually due to the fact that javax.xml.namespace.QName is loaded from the QuarkusClassLoader/RunnerClassLoader (because Quarkus by default will try to load the classes from the QuarkusClassLoader/RunnerClassLoader first) while it should rather be loaded from the System ClassLoader in that particular case.

To workaround this problem you can indeed exclude the dependency that causes the LinkageError if you can exclude all the classes of this dependency otherwise you can rely on the property quarkus.class-loading.parent-first to indicate Quarkus that its classes need to be loaded from the parent ClassLoader first before trying to load it from the QuarkusClassLoader/RunnerClassLoader.

Example of usage of quarkus.class-loading.parent-first in the application.properties :

quarkus.class-loading.parent-first-artifacts=stax:stax-api

I had a similar issue with javax.transaction.xa.XAResource. The issue was that classes that are contained in the JVM and an external dependency (split packages) are always loaded by different classloaders (for development mode or quarkus tests), see https://quarkus.io/guides/class-loading-reference. By removing those split packages (by excludes as mentioned above), the problem is gone. From what i understand, this problem can't appear in production because of the "flat classpath" there.

Related