How to hide warning "Illegal reflective access" in java 9 without JVM argument?

Dmitriy Dumanskiy picture Dmitriy Dumanskiy · Sep 27, 2017 · Viewed 75.7k times · Source

I just tried to run my server with Java 9 and got next warning:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by io.netty.util.internal.ReflectionUtil (file:/home/azureuser/server-0.28.0-SNAPSHOT.jar) to constructor java.nio.DirectByteBuffer(long,int)
WARNING: Please consider reporting this to the maintainers of io.netty.util.internal.ReflectionUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

I would like to hide this warning without adding --illegal-access=deny to JVM options during start. Something like:

System.setProperty("illegal-access", "deny");

Is there any way to do that?

All related answers suggesting to use JVM options, I would like to turn off this from code. Is that possible?

To clarify - my question is about turning this warning from the code and not via JVM arguments/flags as stated in similar questions.

Answer

apangin picture apangin · Sep 28, 2017

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 in IllegalAccessLogger.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
    }
}