JUnit 5 currently builds and runs against JDK 9 early access builds (including Jigsaw builds), but we do not yet have any tests in place that run against user code built with module info.
ModuleUtils with ClassFinder SPIorg.junit.platform.commons.jpmsclazz.getPackage().getImplementationVersion() and related methods for retrieving JAR versioning metadata for classes loaded from named modules.--patch-module module=file(;file)*Hi JUnit team,
Is there a plan to add module-info to junit5 or even better to junit4?
I have a problem using junit4 as unnamed module when testing jdk module, e.g. jaxb-api. It might need to be fixed in JDK though, thus just a question above.
Thank you.
Is there a plan to add module-info to junit5 or even better to junit4?
Regarding JUnit 4, I am not aware of any intent to provide explicit JDK 9 support (even in the form of module-info), especially since JUnit 4 is based on JDK 5. However, perhaps @kcooney or @marcphilipp can better answer that.
Regarding JUnit 5, we are not currently planning to include module-info in JUnit 5 JARs during the 5.0 GA timeline. However, we will keep this on our radar and consider adding explicit Jigsaw module support in later versions.
@avalez we don't want JUnit 4 to require JDK 9, so JUnit 4 will not have a module-info
Thank you for the information!
UPDATE
We cannot even test now with Gradle. 😢
https://github.com/gradle/gradle/issues/723
Attempting to build JUnit 5 against JDK 9-ea+149 results in the following:
java.lang.ExceptionInInitializerError
at org.gradle.initialization.DefaultClassLoaderRegistry.restrictTo(DefaultClassLoaderRegistry.java:40)
at org.gradle.initialization.DefaultClassLoaderRegistry.restrictToGradleApi(DefaultClassLoaderRegistry.java:36)
at org.gradle.initialization.DefaultClassLoaderRegistry.<init>(DefaultClassLoaderRegistry.java:30)
at org.gradle.internal.service.scopes.GlobalScopeServices.createClassLoaderRegistry(GlobalScopeServices.java:224)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:538)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
at org.gradle.internal.service.DefaultServiceRegistry.invoke(DefaultServiceRegistry.java:462)
at org.gradle.internal.service.DefaultServiceRegistry.access$1200(DefaultServiceRegistry.java:84)
at org.gradle.internal.service.DefaultServiceRegistry$FactoryMethodService.invokeMethod(DefaultServiceRegistry.java:796)
at org.gradle.internal.service.DefaultServiceRegistry$FactoryService.create(DefaultServiceRegistry.java:752)
at org.gradle.internal.service.DefaultServiceRegistry$ManagedObjectProvider.getInstance(DefaultServiceRegistry.java:589)
at org.gradle.internal.service.DefaultServiceRegistry$SingletonService.get(DefaultServiceRegistry.java:634)
at org.gradle.internal.service.DefaultServiceRegistry.applyConfigureMethod(DefaultServiceRegistry.java:253)
at org.gradle.internal.service.DefaultServiceRegistry.findProviderMethods(DefaultServiceRegistry.java:214)
at org.gradle.internal.service.DefaultServiceRegistry.addProvider(DefaultServiceRegistry.java:352)
at org.gradle.internal.service.ServiceRegistryBuilder.build(ServiceRegistryBuilder.java:52)
at org.gradle.launcher.cli.BuildActionsFactory.createGlobalClientServices(BuildActionsFactory.java:148)
at org.gradle.launcher.cli.BuildActionsFactory.runBuildInSingleUseDaemon(BuildActionsFactory.java:141)
at org.gradle.launcher.cli.BuildActionsFactory.createAction(BuildActionsFactory.java:89)
at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.createAction(CommandLineActionFactory.java:249)
at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:239)
at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:217)
at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:33)
at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:210)
at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:174)
at org.gradle.launcher.Main.doAction(Main.java:33)
at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:538)
at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:60)
at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:37)
at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:538)
at org.gradle.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:31)
at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:108)
at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected java.lang.Package[] java.lang.ClassLoader.getPackages() accessible: module java.base does not "opens java.lang" to unnamed module @176b75f7
at java.base/jdk.internal.reflect.Reflection.throwInaccessibleObjectException(Reflection.java:427)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:201)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:192)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:186)
at org.gradle.internal.reflect.JavaMethod.<init>(JavaMethod.java:42)
at org.gradle.internal.reflect.JavaMethod.<init>(JavaMethod.java:32)
at org.gradle.internal.reflect.JavaMethod.<init>(JavaMethod.java:36)
at org.gradle.internal.reflect.JavaReflectionUtil.method(JavaReflectionUtil.java:223)
at org.gradle.internal.classloader.FilteringClassLoader.<clinit>(FilteringClassLoader.java:49)
... 47 more
NOTE: this happens even if you add the following to ~/.gradle/gradle.properties.
org.gradle.jvmargs=--add-opens java.base/java.lang=ALL-UNNAMED -Dsun.reflect.debugModuleAccessChecks=true
UPDATE:
The following gets us one step closer.
export _JAVA_OPTIONS="--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED"
But even with that, we now run into the following issue with Ruby regarding java.util.
net.rubygrapefruit.platform.NativeException: Unable to get mutable environment variable map.
at net.rubygrapefruit.platform.internal.WrapperProcess.getEnv(WrapperProcess.java:113)
at net.rubygrapefruit.platform.internal.WrapperProcess.removeEnvInternal(WrapperProcess.java:91)
at net.rubygrapefruit.platform.internal.WrapperProcess.setEnvironmentVariable(WrapperProcess.java:82)
at org.gradle.internal.nativeintegration.processenvironment.NativePlatformBackedProcessEnvironment.removeNativeEnvironmentVariable(NativePlatformBackedProcessEnvironment.java:31)
at org.gradle.internal.nativeintegration.processenvironment.AbstractProcessEnvironment.removeEnvironmentVariable(AbstractProcessEnvironment.java:47)
at org.gradle.internal.nativeintegration.processenvironment.AbstractProcessEnvironment.maybeSetEnvironment(AbstractProcessEnvironment.java:37)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:65)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1161)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.util.Map java.util.Collections$UnmodifiableMap.m accessible: module java.base does not "opens java.util" to unnamed module @e15b7e8
at java.base/jdk.internal.reflect.Reflection.throwInaccessibleObjectException(Reflection.java:427)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:201)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:171)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:165)
at net.rubygrapefruit.platform.internal.WrapperProcess.getEnv(WrapperProcess.java:110)
... 15 more
It looks like we'll have to wait for Gradle to publish something that works with JDK 9, unless somebody else can provide further guidance in the interim.
@sbrannen FWIW I managed to get my gradle working with more of a hack than anything haha
Because Gradle launches these separate applications that use java, it wasn't enough just to add the arguments to JAVA_OPTIONS. Instead I moved $JAVA_HOME/bin/java to $JAVA_HOME/bin/java-real and created a new script in its place. This new script adds all of my options to java before it launches:
#!/bin/sh
# Usage: $JAVA_HOME/bin/java <args>
exec $JAVA_HOME/bin/java-real \
-Dsun.reflect.debugModuleAccessChecks=true \
--add-opens=java.base/java.lang=ALL-UNNAMED \
--add-opens=java.base/java.util=ALL-UNNAMED \
--add-opens=java.base/java.lang.invoke=ALL-UNNAMED \
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED \
--add-opens=java.base/java.io=ALL-UNNAMED \
--add-opens=java.base/java.util.concurrent=ALL-UNNAMED \
--add-opens=java.base/java.text=ALL-UNNAMED \
"$@"
You may need more or less items depending on whats being compiled. After that I also added it to org.gradle.jvmargs in my gradle.properties file!
org.gradle.jvmargs=-Dsun.reflect.debugModuleAccessChecks=true \
--add-opens=java.base/java.lang=ALL-UNNAMED \
--add-opens=java.base/java.util=ALL-UNNAMED \
--add-opens=java.base/java.lang.invoke=ALL-UNNAMED \
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED \
--add-opens=java.base/java.io=ALL-UNNAMED \
--add-opens=java.base/java.util.concurrent=ALL-UNNAMED \
--add-opens=java.base/java.text=ALL-UNNAMED
Also dont forget to update sourceCompatibility = JavaVersion.VERSION_1_9 .. And here's my version info!
ubuntu@ubuntu-xenial:~/workspace$ java -version
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+157)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+157, mixed mode)
ubuntu@ubuntu-xenial:~/workspace$ gradle --version
------------------------------------------------------------
Gradle 3.4
------------------------------------------------------------
Build time: 2017-02-20 14:49:26 UTC
Revision: 73f32d68824582945f5ac1810600e8d87794c3d4
Groovy: 2.4.7
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM: 9-ea (Oracle Corporation 9-ea+157)
OS: Linux 4.4.0-64-generic amd64
This issue originally got me past a sticking point thanks to @cal-pratt, so I thought I would share the new simpler workaround available for the latest Java 9 Jigsaw EA build. I added IgnoreUnrecognizedVMOptions so that it won't cause issues with Java <=8.
JAVA_OPTS is used by the gradle wrapper:
export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions --permit-illegal-access'
gradle.properites:
org.gradle.jvmargs=-XX:+IgnoreUnrecognizedVMOptions --permit-illegal-access
See http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-March/011763.html
@jamespedwards42 unfortunately seems the junit 5 build not/no longer be working under the latest JDK 9 preview:
Using gradle at '/Users/pr/git/junit5/gradlew' to run buildfile '/Users/pr/git/junit5/build.gradle':
java 9-ea
Java(TM) SE Runtime Environment (build 9-ea+161)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+161, mixed mode)
FAILURE: Build failed with an exception.
* What went wrong:
java.lang.ExceptionInInitializerError (no error message)
I have been used the options you described with the additional --show-version to additionally should the actual version. Do you experience the same problem?
@reinhapa Sorry, I haven't tried any of this on this project. But the previous solutions worked for my Gradle Java 9 project. And then this new flag was just announced yesterday.
In order to use the --permit-illegal-access option you need the latest jigsaw build:
https://jdk9.java.net/jigsaw/
▶ java -version
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+161-jigsaw-nightly-h6227-20170321)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+161-jigsaw-nightly-h6227-20170321, mixed mode)
I think it will soon be added to the regular EA builds as well (https://jdk9.java.net/download/)
@jamespedwards42 hmm, just tried it successfully thanks for the tip.
Thanks for sharing your experiences and tips, everybody!
I've also had a look at the Big Kill Switch for disabling strong encapsulation on Java 9, and we'll be investigating further during the M5 time frame.
We'll need to keep an eye on JigSaw as apparently there is not yet a consensus in the expert group. IBM, RedHat and others will vote "no" in the ballot to release the public review. In the past, we've seen major proposals dropped when they failed to meet Java release dead-lines so the question may well be whether Java 9 has module support or not.
Strict module boundaries and JUnit 5 works like a charm: https://github.com/forax/pro/tree/master/src/test/java
Added Related Pull Requests section to the initial issue description.
The sub project junit-platform-commons-java-9 and the sample project junit5-modular-world tackle most of the deliverables listed in the initial description.
Thus, closing this issue. Please open new issues if you encounter problem testing JPMS modules.
@sormuras, can you please _check off_ the Deliverables you covered and mark the ones you didn't cover with an ❌ so that we know what the status quo is?
_reopened in order to address open deliverables_
All covered, all checked.
Thanks! 👍
Most helpful comment
@sbrannen FWIW I managed to get my gradle working with more of a hack than anything haha
Because Gradle launches these separate applications that use java, it wasn't enough just to add the arguments to
JAVA_OPTIONS. Instead I moved$JAVA_HOME/bin/javato$JAVA_HOME/bin/java-realand created a new script in its place. This new script adds all of my options to java before it launches:You may need more or less items depending on whats being compiled. After that I also added it to
org.gradle.jvmargsin mygradle.propertiesfile!Also dont forget to update
sourceCompatibility = JavaVersion.VERSION_1_9.. And here's my version info!