What is an illegal reflective access?
Apart from an understanding of the accesses amongst modules and their respective packages. I believe the crux of it lies in the Module System#Relaxed-strong-encapsulation and I would just cherry-pick the relevant parts of it to try and answer the question.
What defines an illegal reflective access and what circumstances
trigger the warning?
To aid in the migration to Java-9, the strong encapsulation of the modules could be relaxed.
An implementation may provide static access, i.e. by compiled bytecode.
May provide a means to invoke its run-time system with one or more packages of one or more of its modules open to code in all unnamed modules, i.e. to code on the classpath. If the run-time system is invoked in this way, and if by doing so some invocations of the reflection APIs succeed where otherwise they would have failed.
In such cases, you've actually ended up making a reflective access which is "illegal" since in a pure modular world you were not meant to do such accesses.
How it all hangs together and what triggers the warning in what
scenario?
This relaxation of the encapsulation is controlled at runtime by a new launcher option --illegal-access
which by default in Java9 equals permit
. The permit
mode ensures
The first reflective-access operation to any such package causes a
warning to be issued, but no warnings are issued after that point.
This single warning describes how to enable further warnings. This
warning cannot be suppressed.
The modes are configurable with values debug
(message as well as stacktrace for every such access), warn
(message for each such access), and deny
(disables such operations).
Few things to debug and fix on applications would be:-
- Run it with
--illegal-access=deny
to get to know about and avoid opening packages from one module to another without a module declaration including such a directive(opens
) or explicit use of--add-opens
VM arg. - Static references from compiled code to JDK-internal APIs could be identified using the
jdeps
tool with the--jdk-internals
option
The warning message issued when an illegal reflective-access operation
is detected has the following form:WARNING: Illegal reflective access by $PERPETRATOR to $VICTIM
where:
$PERPETRATOR
is the fully-qualified name of the type containing the
code that invoked the reflective operation in question plus the code
source (i.e., JAR-file path), if available, and
$VICTIM
is a string that describes the member being accessed,
including the fully-qualified name of the enclosing type
Questions for such a sample warning: = JDK9: An illegal reflective access operation has occurred. org.python.core.PySystemState
Last and an important note, while trying to ensure that you do not face such warnings and are future safe, all you need to do is ensure your modules are not making those illegal reflective accesses. :)
How can I throw an exception for an illegal reflective access warning?
- Open the Eclipse development environment.
- Choose Run menu –> Run Configurations... –> Java Application –> (your configuration) –> Arguments.
- In the VM arguments text box, type "--illegal-access=deny" [0].
- Click the Apply button.
- Click the Run button.
- Illegal access will throw the java.lang.reflect.InaccessibleObjectException [1].
[0] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-May/012673.html
[1] http://docs.oracle.com/javase/9/docs/api/java/lang/reflect/InaccessibleObjectException.html
How to hide warning Illegal reflective access in java 9 without JVM argument?
There are ways to disable illegal access warning, though I do not recommend doing this.
1. Simple approach
Since the warning is printed to the default error stream, you can simply close this stream and redirect stderr
to stdout
.
public static void disableWarning() {
System.err.close();
System.setErr(System.out);
}
Notes:
- This approach merges error and output streams. That may not be desirable in some cases.
- You cannot redirect warning message just by calling
System.setErr
, since the reference to error stream is saved inIllegalAccessLogger.warningStream
field early at JVM bootstrap.
2. Complicated approach without changing stderr
A good news is that sun.misc.Unsafe
can be still accessed in JDK 9 without warnings. The solution is to reset internal IllegalAccessLogger
with the help of Unsafe API.
public static void disableWarning() {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe u = (Unsafe) theUnsafe.get(null);
Class cls = Class.forName("jdk.internal.module.IllegalAccessLogger");
Field logger = cls.getDeclaredField("logger");
u.putObjectVolatile(cls, u.staticFieldOffset(logger), null);
} catch (Exception e) {
// ignore
}
}
Illegal reflective access by org.springframework.cglib.core.ReflectUtils$1
In JDK 9+, add the following option to the JVM to disable the warning from Spring's use of CGLIB:
--add-opens java.base/java.lang=ALL-UNNAMED
for example:
java --add-opens java.base/java.lang=ALL-UNNAMED -jar target/*.jar
No need to report it; it's a known Spring bug.
This happens because the new JDK 9 module system detected an illegal access that will be disallowed sometime in the (near) future. You can read more about the JDK 9 Module system here.
Update:
A fix for this issue is available JDK 9+ with Spring 5.1+.
Related Topics
Converting an Array of Objects to an Array of Their Primitive Types
Issue Using Imageio.Write Jpg File: Pink Background
What Is the Purpose of @Namedarg Annotation in Javafx 8
Java 8: Difference Between Method Reference Bound Receiver and Unbound Receiver
"Unable to Acquire Application Service" Error While Launching Eclipse
How to Pass Arithmetic Operators to a Method in Java
Java Inetaddress.Getlocalhost(); Returns 127.0.0.1 ... How to Get Real Ip
How to Obtain Mouse Click Coordinates Outside My Window in Java
How to Calculate a Time Span in Java and Format the Output
How to Retrieve Value from Jtextfield in Java Swing
Calling Outer Class Function from Inner Class
Best Way to Make Java's Modulus Behave Like It Should with Negative Numbers
How to Check CPU and Memory Usage in Java
Run Single Test from a Junit Class Using Command-Line
Performance of Traditional for Loop VS Iterator/Foreach in Java
Eclipse: Attach Source/Javadoc to a Library via a Local Property