1. ホーム
  2. java

[解決済み] JVM引数なしでJava 9の警告 "Illegal reflective access "を隠すには?

2023-04-21 22:01:01

質問

Java9でサーバを動かそうとしたら、次のような警告が出ました。

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

この警告を表示しないようにするには --illegal-access=deny をJVMのオプションに追加することなく、この警告を隠したい。何か、こんな感じ。

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

何か方法はないでしょうか?

すべての関連する回答は、JVMオプションを使用することを示唆していますが、私はコードからこれをオフにしたいと思います。それは可能ですか?

明確にするために - 私の質問は、同様の質問で述べられたように、JVM引数/フラグを介してではなく、コードからこの警告を回すことです。

どのように解決するのですか?

不正アクセスの警告を無効にする方法がありますが、あまりお勧めできません。

1. 簡単な方法

警告はデフォルトのエラーストリームに出力されるので、単純にこのストリームを閉じ、リダイレクトして stderrstdout .

public static void disableWarning() {
    System.err.close();
    System.setErr(System.out);
}

注意事項

  • この方法は、エラーと出力のストリームをマージします。それはいくつかのケースでは望ましくないかもしれません。
  • を呼び出すだけでは、警告メッセージをリダイレクトすることはできません。 System.setErr エラーストリームへの参照は IllegalAccessLogger.warningStream フィールドに保存されるため、エラーストリームへの参照はJVMブートストラップの早い段階で

2. stderr を変更しない複雑なアプローチ

良い知らせは sun.misc.Unsafe は、JDK 9 ではまだ警告なしでアクセスできることです。解決策は、内部の IllegalAccessLogger をリセットすることです。

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
    }
}