arquillian / arquillian-core

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.
http://arquillian.org
Apache License 2.0
366 stars 196 forks source link

The new `ThreadLocalUtil` requires the surefire/failsafe JVM's to add `--add-opens=java.base/java.lang=ALL-UNNAMED` #578

Open jamezp opened 3 days ago

jamezp commented 3 days ago
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 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"