Arquillian provides a component model for integration tests, which includes dependency injection and container life cycle management. Instead of managing a runtime in your test, Arquillian brings your test to the runtime.
The ThreadLocalUtil utility introduced in #501 requires the JVM argument --add-opens=java.base/java.lang=ALL-UNNAMED because uses a package-private method ThreadLocal.getMap(). An exception like the following is always logged:
Jul 01, 2024 7:25:57 PM org.jboss.arquillian.core.spi.ThreadLocalUtil cleanThreadLocals
SEVERE: Arquillian failed to cleanup threadlocals - did the Java API change?
java.lang.reflect.InaccessibleObjectException: Unable to make java.lang.ThreadLocal$ThreadLocalMap java.lang.ThreadLocal.getMap(java.lang.Thread) accessible: module java.base does not "opens java.lang" to unnamed module @679d4c1c
at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:391)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:367)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:315)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:203)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:197)
at org.jboss.arquillian.core.spi.ThreadLocalUtil.cleanThreadLocals(ThreadLocalUtil.java:48)
at org.jboss.arquillian.core.spi.ThreadLocalUtil.forceCleanupThreadLocal(ThreadLocalUtil.java:33)
at org.jboss.arquillian.core.impl.ManagerImpl.shutdown(ManagerImpl.java:285)
at org.jboss.arquillian.test.impl.EventTestRunnerAdaptor.shutdown(EventTestRunnerAdaptor.java:163)
at org.jboss.arquillian.junit5.JUnitJupiterTestClassLifecycleManager.close(JUnitJupiterTestClassLifecycleManager.java:55)
at org.junit.jupiter.engine.descriptor.AbstractExtensionContext.lambda$static$0(AbstractExtensionContext.java:45)
at org.junit.platform.engine.support.store.NamespacedHierarchicalStore$EvaluatedValue.close(NamespacedHierarchicalStore.java:333)
at org.junit.platform.engine.support.store.NamespacedHierarchicalStore$EvaluatedValue.access$800(NamespacedHierarchicalStore.java:317)
at org.junit.platform.engine.support.store.NamespacedHierarchicalStore.lambda$close$3(NamespacedHierarchicalStore.java:98)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.store.NamespacedHierarchicalStore.lambda$close$4(NamespacedHierarchicalStore.java:98)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395)
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:261)
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:261)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at org.junit.platform.engine.support.store.NamespacedHierarchicalStore.close(NamespacedHierarchicalStore.java:98)
at org.junit.jupiter.engine.descriptor.AbstractExtensionContext.close(AbstractExtensionContext.java:87)
at org.junit.jupiter.engine.execution.JupiterEngineExecutionContext.close(JupiterEngineExecutionContext.java:53)
at org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor.cleanUp(JupiterEngineDescriptor.java:70)
at org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor.cleanUp(JupiterEngineDescriptor.java:31)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$cleanUp$10(NodeTestTask.java:167)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.cleanUp(NodeTestTask.java:167)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:98)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:198)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:169)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:93)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:58)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:141)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:57)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:103)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:85)
at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47)
at org.apache.maven.surefire.junitplatform.LazyLauncher.execute(LazyLauncher.java:56)
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:184)
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:148)
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:122)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
In general, this feels fairly fragile as a change could result in this not working in future JVM's.
Expected Behaviour
Users should not have to add the opens to the JVM arguments.
Current Behaviour
Users are required to add --add-opens=java.base/java.lang=ALL-UNNAMED to the JVM which launches the test.
Additional Information
$mvn --version
Maven home: /home/jperkins/apps/maven
Java version: 21.0.3, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-21-openjdk-21.0.3.0.9-1.fc40.x86_64
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "6.9.6-200.fc40.x86_64", arch: "amd64", family: "unix"
Issue Overview
The
ThreadLocalUtil
utility introduced in #501 requires the JVM argument--add-opens=java.base/java.lang=ALL-UNNAMED
because uses a package-private methodThreadLocal.getMap()
. An exception like the following is always logged:In general, this feels fairly fragile as a change could result in this not working in future JVM's.
Expected Behaviour
Users should not have to add the opens to the JVM arguments.
Current Behaviour
Users are required to add
--add-opens=java.base/java.lang=ALL-UNNAMED
to the JVM which launches the test.Additional Information
$mvn --version
Maven home: /home/jperkins/apps/maven Java version: 21.0.3, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-21-openjdk-21.0.3.0.9-1.fc40.x86_64 Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "6.9.6-200.fc40.x86_64", arch: "amd64", family: "unix"