Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)

JJUG CCC 2021 Spring にて講演。
2021年3月リリースのJDK 16 では、17個の JEP(JDK Enhancement Proposal)が導入されました。
JDK 16で導入された JEP 396: Strongly Encapsulate JDK Internals by Default による影響は十分に評価・準備することをお勧めします。
今回は、JEP 396での変更点やその背景を解説すると共に、アプリケーションでの評価・確認する際のポイントをご紹介します。

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all
  • Be the first to comment

JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)

  1. 1. JDK 16で導入されたJEP 396にご注意!! JEP 396 : Strongly Encapsulate JDK Internals by Default JJUG CCC 2021 Spring 2021年5月23日 徳益芳郎
  2. 2. Yoshiro Tokumasu Software Engineer https://www.slideshare.net/tokumasu123/presentations 使ってみよう!JDK Flight Recorder 2018年12月11日 徳益 芳郎 Duke 出典:An Oracle blog about Oracle Enterprise Pack for Eclipse「Java 8 Launch!」 ログ出力を改めて考える - JDK Flight Recorder の活用 - 2019年6月27日 徳益 芳郎 Duke 出典:An Oracle blog about Oracle Enterprise Pack for Eclipse「Java 8 Launch!」
  3. 3. はじめに 2021年3月リリースのJDK 16では、17個の JEP(JDK Enhancement Proposal) が導入されました。導入された JEP に関する個々の詳細は、OpenJDK サイト の JDK 16 をご覧ください。 JDK 16 で導入された JEP のうち、JEP 396 : Strongly Encapsulate JDK Internals by Default による影響は十分に評価・準備することをお勧めします。 本セッションでは、JEP 396での変更点やその背景を解説すると共に、アプリ ケーションでの評価・確認する際のポイントをご紹介します。 3
  4. 4. JEP 396 : Strongly Encapsulate JDK Internals by Default
  5. 5. このような警告メッセージを 見たことありませんか? WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.jruby.ext.openssl.SecurityHelper (file:/tmp/jruby-1/ jruby5029500797019692358jopenssl.jar) to field java.security.MessageDigest.provider WARNING: Please consider reporting this to the maintainers of org.jruby.ext.openssl.SecurityHelper 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 5
  6. 6. JEP 396での変更点 従来(JDK 9 ∼ 15) --illegal-access=permit をデフォルト設定としてJava VMが起動する 今後(JDK 16以降) --illegal-access=deny をデフォルト設定としてJava VMが起動する 6
  7. 7. JEP 396による影響 モジュール化していないアプリケーションやライブラリ(OSSを含む)にて、 sun.* や com.sun.* パッケージを含むJDK内部APIを利用している場合、 アプリケーション実行時に InaccessibleObjectException などの ランタイム例外が発生する 7
  8. 8. JEP 396の背景 JDK 9リリース時に導入されたモジュール化ですが、完全なカプセル化を 強制すると影響が大きいということで、妥協した状態(--illegal- access=permit:Relaxed strong encapsulation)で導入され、JDK内部 APIを利用しない実装へ改修するための移行期間を設けていた しかし次のLTS(Long Term Support)候補であるJDK 17のリリース (2021年9月予定)が見えてきた今(JDK 16 リリース時)、次の段階 (--illegal-access=deny:Strong encapsulation)に進むことになる 8
  9. 9. モジュールに対するアクセス制御 モジュールシステムの基本
  10. 10. モジュール化 従来のJARファイル module foo { exports bar; opens fizz; requires buzz; } モジュール定義 module-info モジュラJARファイル 10
  11. 11. アクセス制御はモジュール定義に従う module- info module- info Direct Reflection Deep
 Reflection module bar { exports a; } module- info module fizz { exports c; opens c; } module foo { requires bar; requires buzz; } module- info module buzz { exports b; opens b; } <凡例>  :モジュール定義に従いアクセスできない(例外発生) 11 foo bar fizz buzz
  12. 12. モジュールの分類 モジュールシステムにおける経過措置
  13. 13. モジュール対応状況と配備場所 Unnamed Modules --class-path --module-path 従来のJARファイル 従来のJARファイル module- info モジュラJARファイル module- info モジュラJARファイル module- info Automatic Modules Named Modules 無視 生成 13 JARファイル名 モジュール名 module- info 生成 モジュール名がない! module- info 生成 モジュール名がない!
  14. 14. Unnamed / Automatic Modulesの扱い モジュール定義 Unnamed Modules Automatic Modules name なし Jarファイル名 または、 JarファイルのMANIFEST属性で指定 requires ALL-MODULE-PATH ALL-UNNAMED ALL-SYSTEM ALL-MODULE-PATH ALL-UNNAMED ALL-SYSTEM exports *(全て公開) *(全て公開) opens *(全て許可) *(全て許可) 14
  15. 15. モジュールの分類 System Modules Unnamed Modules Automatic Modules Named Modules module- info fizz module- info module- info 15 module- info ⁉ モジュール名がない! 経過措置:将来は削除される予定だが、JDK 16 でも継続される JARファイル名 モジュール名
  16. 16. モジュール分類間のアクセス制御 Illegal-access が発生する箇所(モジュール分類間)を知る!
  17. 17. モジュールの分類 System Modules Unnamed Modules Automatic Modules Named Modules module- info fizz module- info module- info 17 module- info ⁉ モジュール名がない! JARファイル名 モジュール名 再掲載
  18. 18. module- info Automatic Modules Unnamed Modules → Automatic Modules Unnamed Modules 18 ⁉ module- info モジュール名がない! Unnamed Modules は、 Automatic Modules を含む全てのモジュールを 参照(requires)と定義されている JARファイル名 モジュール名 module fileA { exports *; opens *; } 全てのパッケージを公開 全てのパッケージへの Deep Reflection を許可 <凡例>   :モジュール定義に従いアクセス制御される Direct Reflection Deep
 Reflection
  19. 19. module- info Automatic Modules Automatic Modules → Unnamed Modules Unnamed Modules 19 Direct Reflection Deep
 Reflection module ⁉ { exports *; opens *; } 全てのパッケージを公開 全てのパッケージへの Deep Reflection を許可 ⁉ module- info Automatic Modules は、 Unnamed Modules を含む全てのモジュールを 参照(requires)と定義されている モジュール名がない! JARファイル名 モジュール名 <凡例>   :モジュール定義に従いアクセス制御される
  20. 20. Unnamed Modules → Named Modules ⁉ module- info モジュール名がない! fizz module- info Named Modules Unnamed Modules は、 Named Modules を含む全てのモジュールを 参照(requires)と定義されている <凡例>   :モジュール定義に従いアクセス制御される Direct Reflection Deep
 Reflection module fizz { exports D; opens D; } モジュール定義の内容は、 モジュール毎に異なる Unnamed Modules 20
  21. 21. module- info Automatic Modules Automatic Modules → Named Modules 21 JARファイル名 モジュール名 <凡例>   :モジュール定義に従いアクセス制御される fizz module- info Named Modules Direct Reflection Deep
 Reflection Automatic Modules は、 Named Modules を含む全てのモジュールを 参照(requires)と定義されている module fizz { exports D; opens D; } モジュール定義の内容は、 モジュール毎に異なる
  22. 22. Named Modules → Unnamed Modules Unnamed Modules fizz module- info Named Modules 22 Direct Reflection Deep
 Reflection ⁉ <凡例>  :Named Modules のモジュール定義にて requires 指定できないので、アクセスできない module ⁉ { exports *; opens *; } Unnamed Modules は、 モジュール名がない module- info モジュール名がない! Named Modules は、 参照したいモジュールを requires で定義する必要がある
  23. 23. module- info Automatic Modules Named Modules → Automatic Modules 23 JARファイル名 モジュール名 <凡例>   :モジュール定義に従いアクセス制御される fizz module- info Named Modules module fizz { exports D; opens D; requires fileA; } Named Modules は、 参照したいモジュールを requires で定義する必要がある module fileA { exports *; opens *; } 全てのパッケージを公開 全てのパッケージへの Deep Reflection を許可 Direct Reflection Deep
 Reflection
  24. 24. module- info Automatic Modules Automatic Modules → System Modules 24 Direct Reflection Deep
 Reflection Automatic Modules は、 System Modules を含む全てのモジュールを 参照(requires)と定義されている JARファイル名 モジュール名 System Modules module- info module buzz { exports D; } モジュール定義の内容は、 モジュール毎に異なる <凡例>   :モジュール定義に従いアクセス制御される
  25. 25. Unnamed Modules → System Modules 25 System Modules module- info Unnamed Modules ⁉ module- info モジュール名がない! module buzz { exports D; } Unnamed Modules は、 System Modules を含む全てのモジュールを 参照(requires)と定義されている Direct Reflection Deep
 Reflection ! --illegal-access=permit JDK 15 以前の挙動 ! ! <凡例>   :モジュール定義に反して常にアクセス可能(警告メッセージ) !
  26. 26. モジュール定義に反して常にアクセス可能 $ java --show-version Main2.java openjdk 15.0.2 2021-01-19 OpenJDK Runtime Environment (build 15.0.2+7-27) OpenJDK 64-Bit Server VM (build 15.0.2+7-27, mixed mode, sharing) WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by Main2 (file:/2021/Main2.java) to method java.util.concurrent.ThreadPoolExecutor.addWorker(java.lang.Runnable,boolean) WARNING: Please consider reporting this to the maintainers of Main2 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 26
  27. 27. Unnamed Modules → System Modules 27 System Modules module- info Unnamed Modules ⁉ module- info モジュール名がない! module buzz { exports D; } モジュール定義の内容は、 モジュール毎に異なる Unnamed Modules は、 System Modules を含む全てのモジュールを 参照(requires)と定義されている Direct Reflection Deep
 Reflection --illegal-access=deny JDK 16 以降の挙動 <凡例>   :モジュール定義に従いアクセス制御される
  28. 28. モジュール定義に従いアクセス制御される $ java --show-version Main2.java openjdk 16 2021-03-16 OpenJDK Runtime Environment (build 16+35-2229) OpenJDK 64-Bit Server VM (build 16+35-2229, mixed mode, sharing) java.lang.reflect.InaccessibleObjectException: Unable to make private boolean java.util.concurrent.ThreadPoolExecutor.addWorker(java.lang.Runnable,boolean) accessible: module java.base does not "opens java.util.concurrent" to unnamed module @7f416310 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.Method.checkCanSetAccessible(Method.java:199) at java.base/java.lang.reflect.Method.setAccessible(Method.java:193) at Main3.main(Main2.java:18) 28 RuntimeException
  29. 29. JDK内部API System Modules の非公開な APIのうち、 --illegal-access=deny の影響を受ける箇所(分類)を知る!
  30. 30. JDK内部API 本来、アプリケーションやライブラリで利用されることを想定していない 非公開な API であり、sun.* や com.sun.* または jdk.* パッケージなど… ここでは、以下の3つに分類する 代替APIが存在する 影響が大きい その他 30 System Modules module- info
  31. 31. 代替APIが存在する JDK内部API https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool 31 JDK 8の時点で既に代替APIが提供されており、現在は削除されている 標準API JDK内部API 標準API JDK内部API
  32. 32. 影響が大きい JDK内部API 重要な機能を提供しているが、現時点でも代替APIが存在しない… 経過措置:jdk.unsupported モジュールに格納されて提供されている 将来は削除される予定だが、JDK 16 でも継続される sun.misc.Signal sun.misc.SignalHandler sun.misc.Unsafe sun.reflect.Reflection::getCallerClass(int) sun.reflect.ReflectionFactory com.sun.nio.file.ExtendedCopyOption com.sun.nio.file.ExtendedOpenOption com.sun.nio.file.ExtendedWatchEventModifier com.sun.nio.file.SensitivityWatchEventModifier $ java --describe-module jdk.unsupported jdk.unsupported@16 exports com.sun.nio.file exports sun.misc exports sun.reflect requires java.base mandated opens sun.misc opens sun.reflect JDK 9 で代替APIが提供され たのでJDK 11で削除された 32
  33. 33. その他 JDK内部API ① 他の分類に該当しない、sun.* や com.sun.* パッケージなどの非公開パッケージ JDK 9以降の環境では、基本的にカプセル化されている(アクセス不可) 経過措置(JDK15まで):実行時に限り、Unnamed module に対して公開 (exports) ② 全パッケージに含まれる private クラスやメソッド、フィールドなど… Deep Reflection によるアクセスを必須とする 経過措置(JDK15まで):Unnamed module に対して deep reflection を許可 (opens) 33
  34. 34. JDK内部APIの分類とその影響 JEP 396(--illegal-access のパラメータを permit から deny に変更)の影響 がJDK内部APIの分類に応じて異なる JDK内部APIの分類 --illegal-access=permit --illegal-access=deny 代替APIが存在する ❌ (NoClassDefFoundError などが発生) ❌ (NoClassDefFoundError などが発生) 影響が大きい (jdk.unsupported モジュール) ✔ ✔ その他 ✔ ❌ (InaccessibleObjectException などが発生) <凡例> ✔:問題なくアクセス可能 ❌:アクセス不可(例外が発生する) 34 JDK 16 のデフォルト値
  35. 35. --illegal-access=<parameter> Java VM 起動オプション
  36. 36. Unnamed Module による許可されていないJDK内部APIへのアクセスに対 する挙動を、パラメータ値に応じて制御する --illegal-access のパラメータと挙動 パラメータ値 初回アクセス 2回目以降のアクセス 補足 permit △ ✔ JDK 9 ∼15のデフォルト値 warn △ △ ー debug △ (スタックトレースも出力) △ (スタックトレースも出力) ー deny ❌ ❌ JDK 16以降のデフォルト値 <凡例> ✔:問題なくアクセス可能 △:アクセス可能(但し、警告メッセージを出力) ❌:アクセス不可(例外が発生する) 36
  37. 37. --illegal-access=warn の場合 $ java --show-version --illegal-access=warn Main2.java openjdk 15.0.2 2021-01-19 OpenJDK Runtime Environment (build 15.0.2+7-27) OpenJDK 64-Bit Server VM (build 15.0.2+7-27, mixed mode, sharing) WARNING: Illegal reflective access by Main2 (file:/2021/Main2.java) to method java.util.concurrent.ThreadPoolExecutor.addWorker(java.lang.Runnable,boolean) WARNING: Illegal reflective access by Main2 (file:/2021/Main2.java) to method java.util.concurrent.ThreadPoolExecutor.addWorker(java.lang.Runnable,boolean) WARNING: Illegal reflective access by Main2 (file:/2021/Main2.java) to field com.sun.crypto.provider.BlowfishConstants.BLOWFISH_BLOCK_SIZE 37 警告メッセージ(許可されないアクセスの回数分)
  38. 38. --illegal-access=debug の場合 $ java --show-version --illegal-access=debug Main2.java openjdk 15.0.2 2021-01-19 OpenJDK Runtime Environment (build 15.0.2+7-27) OpenJDK 64-Bit Server VM (build 15.0.2+7-27, mixed mode, sharing) WARNING: Illegal reflective access by Main2 (file:/2021/Main2.java) to method java.util.concurrent.ThreadPoolExecutor.addWorker(java.lang.Runnable,boolean) at Main2.main(Main2.java:18) WARNING: Illegal reflective access by Main2 (file:/2021/Main2.java) to method java.util.concurrent.ThreadPoolExecutor.addWorker(java.lang.Runnable,boolean) at Main2.main(Main2.java:26) WARNING: Illegal reflective access by Main2 (file:/2021/Main2.java) to field com.sun.crypto.provider.BlowfishConstants.BLOWFISH_BLOCK_SIZE at Main2.main(Main2.java:35) 38 警告メッセージとスタックトーレス(許可されないアクセスの回数分)
  39. 39. 影響ある箇所の特定方法は⁉ その他 に分類されるJDK内部APIを利用する箇所を特定する
  40. 40. JDK内部APIの分類とその影響 JEP 396(--illegal-access のパラメータを permit から deny に変更)の影響 がJDK内部APIの分類に応じて異なる JDK内部APIの分類 --illegal-access=permit --illegal-access=deny 代替APIが存在する ❌ (NoClassDefFoundError などが発生) ❌ (NoClassDefFoundError などが発生) 影響が大きい (jdk.unsupported モジュール) ✔ ✔ その他 ✔ ❌ (InaccessibleObjectException などが発生) <凡例> ✔:問題なくアクセス可能 ❌:アクセス不可(例外が発生する) 40 JDK 16 のデフォルト値 再掲載
  41. 41. JDK内部APIを利用するコード例 try { sun.misc.BASE64Encoder b64 = new sun.misc.BASE64Encoder(); System.out.println(b64.encode(new byte[]{1, 2, 3})); } catch (Throwable ex) { ex.printStackTrace(); } try { Field field = sun.misc.Unsafe.class.getDeclaredField(“theUnsafe"); field.setAccessible(true); sun.misc.Unsafe unsafe = (sun.misc.Unsafe) field.get(null); } catch (Exception ex) { ex.printStackTrace(); } try { java.util.conccurent.ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); Method addWorker = ThreadPoolExecutor.class.getDeclaredMethod(“addWorker", Runnable.class, Boolean.TYPE); addWorker.setAccessible(true); addWorker.invoke(executor, null, Boolean.FALSE); } catch (Exception ex) { ex.printStackTrace(); } その他 41 Deep Reflection 代替APIが存在する 影響が大きい
  42. 42. jdeps ツールで確認⁉ $ jdeps --jdk-internals --class-path test.legacy.main.jar test.legacy.main.jar -> jdk8internals test.legacy.main.jar -> jdk.unsupported test.main.Main -> sun.misc.BASE64Encoder JDK internal API (jdk8internals) test.main.Main -> sun.misc.Unsafe JDK internal API (jdk.unsupported) 警告: JDK内部APIはサポートされておらず、JDK実装専用ですが、互換性なしで 削除または変更される場合があり、アプリケーションを中断させる可能性があります。 JDK内部APIの依存性を削除するようコードを変更してください。 JDK内部APIの置換に関する最新の更新については、次を確認してください: https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool JDK内部API 修正候補 -------- ---- sun.misc.BASE64Encoder Use java.util.Base64 @since 1.8 sun.misc.Unsafe See http://openjdk.java.net/jeps/260 42
  43. 43. jdeps ツールで確認する際の注意点 --jdk-internals オプションで確認できる JDK内部API の種類は限られる! JDK内部APIの分類 jdepsツールでの確認 例 代替APIが存在する ✔ sun.misc.BASE64Decoder sun.reflect.Reflection.getCallerClass 影響が大きい (jdk.unsupported モジュール) ✔ sun.misc.Unsafe com.sun.nio.file.ExtendedCopyOption その他 ❌ java.util.concurrent.ThreadPoolExecutor.addWorker java.security.MessageDigest.provider sun.security.util.SecurityConstants <凡例> ✔:確認できる ❌:確認できない 43 direct アクセスの箇所のみ検出できる
  44. 44. ⁉ setAccessible(true) の箇所を特定⁉ 全てのソースコード(商用版を含む)を保持しているなら可能かもねぇ… OSSの場合でもマイナーバージョンまで完全把握していないとねぇ… System modules 以外のモジュールに対する箇所もヒットするけどねぇ… やらないより、やる価値はあるので、自作のソースコードだけでも! 44
  45. 45. JDK 16 以降に向けた準備・確認 以下のように JEP 396 による影響を確認する 1.--illegal-access=debug を明示的に指定して Java VM を起動する 警告メッセージとスタックトレースを基に修正すべき箇所を確認する 2.--illegal-access=deny を明示的に指定して Java VM を起動する 例外が発生することなく、アプリケーションが正常動作することを確認する 45
  46. 46. JDK 16 で実行してみた…
  47. 47. JDK 16 では、やっぱり例外発生! $ java --show-version Main3.java openjdk 16 2021-03-16 OpenJDK Runtime Environment (build 16+35-2229) OpenJDK 64-Bit Server VM (build 16+35-2229, mixed mode, sharing) java.lang.reflect.InaccessibleObjectException: Unable to make private boolean java.util.concurrent.ThreadPoolExecutor.addWorker(java.lang.Runnable,boolean) accessible: module java.base does not "opens java.util.concurrent" to unnamed module @7f416310 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.Method.checkCanSetAccessible(Method.java:199) at java.base/java.lang.reflect.Method.setAccessible(Method.java:193) at Main3.main(Main3.java:18) 47 RuntimeException
  48. 48. ソースコード修正なしに対処するには… $ java --show-version --add-opens java.base/java.util.concurrent=ALL-UNNAMED Main3.java openjdk 16 2021-03-16 OpenJDK Runtime Environment (build 16+35-2229) OpenJDK 64-Bit Server VM (build 16+35-2229, mixed mode, sharing) 48 この対処は、リスクをともなうので注意が必要である モジュール提供者の意思に反している! JDK内部APIが変更・削除された場合、失敗する!
  49. 49. JDK 16 では --illegal-access は deprecated $ java --show-version --illegal-access=permit Main3.java OpenJDK 64-Bit Server VM warning: Option --illegal-access is deprecated and will be removed in a future release. openjdk 16 2021-03-16 OpenJDK Runtime Environment (build 16+35-2229) OpenJDK 64-Bit Server VM (build 16+35-2229, mixed mode, sharing) WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by Main3 (file:/2021/Main3.java) to method java.util.concurrent.ThreadPoolExecutor.addWorker(java.lang.Runnable,boolean) WARNING: Please consider reporting this to the maintainers of Main3 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 49 警告メッセージ(初回アクセス分のみ)
  50. 50. まとめ
  51. 51. JEP 396での変更点 従来(JDK 9 ∼ 15) --illegal-access=permit をデフォルト設定としてJava VMが起動する 今後(JDK 16以降) --illegal-access=deny をデフォルト設定としてJava VMが起動する 51 再掲載
  52. 52. Unnamed Modules → System Modules 52 System Modules module- info Unnamed Modules ⁉ module- info モジュール名がない! module buzz { exports D; } モジュール定義の内容は、 モジュール毎に異なる Unnamed Modules は、 System Modules を含む全てのモジュールを 参照(requires)と定義されている Direct Reflection Deep
 Reflection --illegal-access=permit JDK 15 以前の挙動 再掲載 ! ! <凡例>   :モジュール定義に反して常にアクセス可能(警告メッセージ) ! !
  53. 53. Unnamed Modules → System Modules 53 System Modules module- info Unnamed Modules ⁉ module- info モジュール名がない! module buzz { exports D; } モジュール定義の内容は、 モジュール毎に異なる Unnamed Modules は、 System Modules を含む全てのモジュールを 参照(requires)と定義されている Direct Reflection Deep
 Reflection --illegal-access=deny JDK 16 以降の挙動 <凡例>   :モジュール定義に従いアクセス制御される 再掲載
  54. 54. その他 JDK内部API ① 他の分類に該当しない、sun.* や com.sun.* パッケージなどの非公開パッケージ JDK 9以降の環境では、基本的にカプセル化されている(アクセス不可) 経過措置(JDK15まで):実行時に限り、Unnamed module に対して公開 (exports) ② 全パッケージに含まれる private クラスやメソッド、フィールドなど… Deep Reflection によるアクセスを必須とする 経過措置(JDK15まで):Unnamed module に対して deep reflection を許可 (opens) 54 再掲載
  55. 55. JDK 16 以降に向けた準備・確認 以下のように JEP 396 による影響を確認する 1.--illegal-access=debug を明示的に指定して Java VM を起動する 警告メッセージとスタックトレースを基に対処すべき箇所を確認する 2.--illegal-access=deny を明示的に指定して Java VM を起動する 例外が発生することなく、アプリケーションが正常動作することを確認する 55 再掲載
  56. 56. --add-opens/--add-exports のリスク $ java --show-version --add-opens java.base/java.util.concurrent=ALL-UNNAMED Main2.java openjdk 16 2021-03-16 OpenJDK Runtime Environment (build 16+35-2229) OpenJDK 64-Bit Server VM (build 16+35-2229, mixed mode, sharing) 56 この対処は、リスクをともなうので注意が必要である モジュール提供者の意思に反している! JDK内部APIが変更・削除された場合、失敗する!
  57. 57. APPENDIX
  58. 58. 参考情報 JDK 16 - OpenJDK - https://openjdk.java.net/projects/jdk/16/ JEP 396: Strongly Encapsulate JDK Internals by Default https://openjdk.java.net/jeps/396 Relaxed Strong encapsulation - JEP 261: Module System - https://openjdk.java.net/jeps/261#Relaxed-strong-encapsulation 58
  59. 59. 参考情報 JEP 260: Encapsulate Most Internal APIs https://openjdk.java.net/jeps/260 Replace uses of the JDK’s internal APIs - Java Dependency Analysis Tool - https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool Internal packages that will no longer be open by default 
 / Exported packages that will no longer be open by default https://cr.openjdk.java.net/~mr/jigsaw/jdk8-packages-denied-by-default 59
  60. 60. その他 使ってみよう!JDK Flight Recorder https://www.slideshare.net/tokumasu123/jdk-flight-recorder-126001298 ログ出力を改めて考える - JDK Flight Recorder の活用 - https://www.slideshare.net/tokumasu123/jdk-flight-recorder-155345312 JFR Event Streaming によるAP監視 - JDK Flight Recorder の活用 - https://www.slideshare.net/tokumasu123/jfr-event-streamingap-jdk-flight-recorder 60
  61. 61. END “JDK 16 で導入された JEP 396 にご注意” JEP 396 : Strongly Encapsulate JDK Internals by Default

×