system-lambda
system-lambda copied to clipboard
System lambda is incompatible with JDK 16.
I'm seeing:
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 @50134894
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:357)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:177)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:171)
at com.github.stefanbirkner.systemlambda.SystemLambda$WithEnvironmentVariables.getFieldValue(SystemLambda.java:1380)
at com.github.stefanbirkner.systemlambda.SystemLambda$WithEnvironmentVariables.getEditableMapOfVariables(SystemLambda.java:1340)
at com.github.stefanbirkner.systemlambda.SystemLambda$WithEnvironmentVariables.restoreOriginalVariables(SystemLambda.java:1318)
at com.github.stefanbirkner.systemlambda.SystemLambda$WithEnvironmentVariables.execute(SystemLambda.java:1233)
Any work arounds?
See also https://github.com/webcompere/system-stubs/issues/32
A possible workaround is to pass the --illegal-access=warn argument to the JVM
At this point, it looks like the JDK folks are closing the loophole which allows us to hack the environment variables. A longer-term solution may be to somehow statically mock System
, but libraries like Mockito
can't safely do that yet.
With Java 17 comes JEP 403: Strongly Encapsulate JDK Internals (JDK-8266851).
Quoting from the release-notes:
The java launcher option --illegal-access is obsolete. If used on the command line it causes a warning message to be issued, and otherwise has no effect. Existing code that must use internal classes, methods, or fields of the JDK can still be made to work by using the --add-opens launcher option
E.g. --add-opens=java.base/java.util.jar=ALL-UNNAMED
Just wondering if there is any update on this - These mocking rules are invaluable, so it's disappointing to see that they don't play well with the latest Long Term Java release
According to @TheSnoozer reply, this snippet for maven permits to execute JUnit tests without problems
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</dependency>
</dependencies>
<configuration>
<argLine>--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED</argLine>
</configuration>
</plugin>
@henryx - this will undoubtedly be a temporary measure - it essentially continues Java supporting the core illegal reflective access that it's trying to rule out.
@stefanbirkner - you can copy from https://github.com/webcompere/system-stubs/blob/main/system-stubs-core/src/main/java/uk/org/webcompere/systemstubs/environment/EnvironmentVariableMocker.java if you wish
https://github.com/webcompere/system-stubs which started life as a fork of this project has now a solution which does not use reflection. However, it does use mockito-inline
, which may be undesirable for some folks.
Any news on this? Would love to be able to use jdk17
There's limited support (single threaded only) for this in https://github.com/webcompere/system-stubs - @stefanbirkner is welcome to steal the implementation from the above to retrofit to system lambda. System stubs supports all of system lambda's original functionality and to adopt it you'd just need to switch the package imports.
De acuerdo a@TheSnoozerrespuesta, este fragmento para maven permite ejecutar pruebas JUnit sin problemas
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <dependencies> <dependency> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </dependency> </dependencies> <configuration> <argLine>--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED</argLine> </configuration> </plugin>
What does that configuration inside argLine really do?
https://docs.oracle.com/en/java/javase/11/migrate/index.html#JSMIG-GUID-12F945EB-71D6-46AF-8C3D-D354FD0B1781