10のJava9で変わるJava8の嫌なとこ!

724 views

Published on

10のJava9で変わるJava8の嫌なとこ!

Published in: Technology

10のJava9で変わるJava8の嫌なとこ!

  1. 1. 10のJava9で変わるJava8の嫌なとこ!
  2. 2. ● Java9で解決されるJava8で嫌なことランキング – 個人的主観に基づく – どのように解決されるかを紹介 – Java9に上げるときに,気をつけることなども紹介 ● 細かくは紹介しないので,気になったものがあった ら調べてください – 過去のリリースの既知の事も詳しく説明しない
  3. 3. Jigsaw(モジュール化) JShell(JavaのREPL) G1GCデフォルト化
  4. 4. 10位 コンパイルに時間かかりすぎ
  5. 5. コンパイルに時間かかりすぎ class C<T> { C() {} C(T t) {} C(C<T> c) {} static <U> C<U> m(C<U> c) {return c;} public static void main(String... args) { C<String> c = m(new C<>(m(new C<>(m(new C<>())))); // 1秒以下 } }
  6. 6. コンパイルに時間かかりすぎ m(new C<>( m(new C<>( m(new C<>( m(new C<>( m(new C<>()))))))))) // ネスト5: Javac(2.02s), ECJ(1.17s)
  7. 7. コンパイルに時間かかりすぎ m(new C<>( m(new C<>( m(new C<>( m(new C<>( m(new C<>( m(new C<>( m(new C<>()))))))))))))) // ネスト7: Javac(14.99s) ECJ(10.82s)
  8. 8. コンパイルに時間かかりすぎ m(new C<>( m(new C<>( m(new C<>( m(new C<>( m(new C<>( m(new C<>( m(new C<>( m(new C<>( m(new C<>( m(new C<>()))))))))))))))))))) //ネスト10
  9. 9. コンパイルに時間かかりすぎ 1分? 10分? 20分? 60分/それ以上?
  10. 10. 60分以上
  11. 11. コンパイルに時間かかりすぎ ● 型検査とオーバロード解決/型推論は同時に行う – m(new C<>(expr)) ● C(T)と仮定して,exprの型検査とオーバロード解決/型推論 ● C(C<U>)と仮定して,exprの型検査とオーバロード解決/型推論 – expr=m(new C<>(expr1))なら指数的に増加
  12. 12. コンパイルに時間かかりすぎ ● オーバロード数Nとすると – N*3回,exprの型検査とオーバロード解決/型推論 ● Strict, Loose, Varargs for each of overloaded methods
  13. 13. Tiered Attribution ● 型検査とオーバーロード解決/型推論を分離 ● 型検査 – オーバーロード解決内でやる必要は無かった ● オーバーロード解決/型推論 – 実引数に構造的な型与える ● 推論が必要な場合,型推論情報を持つ – 何度も同じ式を処理しない(メモ化)
  14. 14. 1秒以下
  15. 15. 4000倍
  16. 16. 9位 Stringの+のコード生成がイケてない
  17. 17. String +のコード生成 String s = “aaa” + hoge + foo ↓ StringBuilder s$sb = new StringBuilder(); s$sb.append(“aaa”).append(hoge).append(foo); String s = s$sb.toString();
  18. 18. String +のコード生成 ● 将来のJDKでFastestStringBuilderが実装されたら – 過去のJDKでコンパイルされたコード ● StringBuilderに強く依存 ● 将来のJDKで動かしてもFastestStringBuilderが使われない – 実際にこれは過去にあったこと ● StringBufferからStringBuilderに – 全てのコードをコンパイルし直す必要 ● コンパイラのメンテナンスコスト大 – コード生成処理って,地獄・・・
  19. 19. invokedynamicを使う public java.lang.String m(java.lang.String, int); descriptor: (Ljava/lang/String;I)Ljava/lang/String; flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=3 0: aload_1 1: iload_2 2: invokedynamic #5, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String; 7: areturn
  20. 20. invokedynamicを使う ● ライブラリが文字列連結 ● 将来のJDKでFastestStringBuilderが実装された ら – 過去のJDKでコンパイルされたコード ● FastestStringBuilderが使われる – コンパイルし直す必要なし!
  21. 21. 懸念点 ● Android N未満だと動かなくなるかも? – invokedynamic解釈できない – -XdstringConcat=inline でレガシーバイトコード生成
  22. 22. 8位 匿名クラスにダイアモンド演算子 が使えない!
  23. 23. 匿名クラス+ダイアモンド演算子 List<String> list = new ArrayList<String>() {{ add(“hoge”); }}; // JAX-RS client List<String> res = target.get(new GenericType<String>(){});
  24. 24. 使えるようになります List<String> list = new ArrayList<>() {{ add(“hoge”); }}; // JAX-RS client List<String> res = target.get(new GenericType<>(){});
  25. 25. 7位 Javadocイケてない! 検索もできない! HTML4で時代遅れ!
  26. 26. 検索できるようになります!
  27. 27. 検索できるようになります!
  28. 28. モジュールがトップに表示 ● 頑張ってどのパッケージがどのモジュールに属すか 覚えましょう
  29. 29. 6位 Deprecated意味ない,情報少ない
  30. 30. @Decprecated @Deprecated public void stop() {…} ● どういうDeprecated??? – いつDeprecatedになったの??? – いつか削除されるの???
  31. 31. @Deprecatedが変わる! @Deprecated( forRemoval = false, // 将来削除される? since = “1.2”) // いつからDepr.に? public void stop() {...}
  32. 32. Changin Depr. In JDK ● add @Deprecated to constructors for boxed primitives (Boolean, Integer, etc.) (JDK-8145468) ● add @Deprecated(forRemoval=true) to the Runtime.traceInstructions and Runtime.traceMethodCalls methods (JDK-8153330) ● add @Deprecated to various java.applet and related classes (JEP 289) ● add @Deprecated to java.util.Observable and Observer (JDK-8154801) ● add @Deprecated(forRemoval=true) to various superseded security APIs, including java.security.acl (JDK- 8157847), javax.security.cert and com.sun.net.ssl (JDK-8157712), java.security.Certificate (JDK-8157707), and javax.security.auth.Policy (JDK-8157848) ● add @Deprecated to "legacy collection" implementations Dictionary, Enumeration, Hashtable, Stack, and Vector (JDK-8145469) ● add @Deprecated to java.util.Timer and TimerTask (JDK-8154799) ● add @Deprecated to the Optional.get method (JDK-8160606) ● add @Deprecated to java.util.Date, Calendar, and related classes (JDK-8164898) ● add @Deprecated to java.lang.Compiler (JDK-4285505) ● add @Deprecated to the java.corba module ● modify already-deprecated methods Thread.destroy(), Thread.stop(Throwable), Thread.countStackFrames(), System.runFinalizersOnExit(), and various disused Runtime and SecurityManager methods to have @Deprecated(forRemoval=true) (JDK-8145468) ● remove @Deprecated from java.awt.Component.show and hide
  33. 33. 警告のルールも変わる! | API declaration site use site | not dep. forRemoval context | false true +---------------------------------- not dep. | 警告 警告 forRemoval=false | 警告 forRemoval=true | 警告
  34. 34. @SuprressWarning ● “deprecation” – forRemoval = falseの警告を抑制 ● “removal” – forRemoval = trueの警告を抑制 ● 両方抑えたかったら – @SuppressWarning({“deprecation”, “removal”})
  35. 35. jdeprscan ● jar内のDeprecatedなAPIの使用を検出
  36. 36. 5位 Collectionのstaticファクトリー無いの不便
  37. 37. 初期値付き不変コレクション生成 ● Arrays.asList(“abc”); ● Set<String> s = Collections.unmodifiableSet( new HashSet<>(Arrays.asList(“abc”))); ● Collections.unmodifiableSet( new HashMap<Integer, String>() {{ put(0, “hoge”); }});
  38. 38. staticファクトリーできました! ● List#of – List.of(“abc”) ● Set#of – Set.of(“abc”) ● Map#of – Map.of(0, “hoge”) – Map.ofEntries(Map.entry(0, “hoge”)) ● それぞれ0〜10要素までオーバロード – それ以上は可変長引数 ● 全てイミュータブル – 変更,追加しようとすると例外
  39. 39. Guava使ってるなら要らない?
  40. 40. 4位 Stream全然便利じゃない!
  41. 41. Infinit Stream Stream.iterate(1, i → i*2+3)... Stream.generate(() → new Hoge())... ● このまま終端操作を実行すると,無限ループに – forEach, collect, reduce – Finite Streamにする必要がある
  42. 42. To Finite Stream ● limit(n) – 先頭からn件の有限Streamに ● これ以外に手段がない! – ある条件を満たすまで,とか
  43. 43. 条件でskip/limitできるように ● takeWhile(Predicate) – 条件でlimit – Stream.iterate(1, i → i*2+3) .takeWhile(i → i < 100)... ● dropWhile(Predicate) – 条件を満たす間skip
  44. 44. for文的Stream生成 ● Stream#iterate(T t, Predicate p, T→T next) – for (T t; p.test(t); t = next.apply(t)) {…} – Stream.iterate(2, i → i<100, i → i*2+3)
  45. 45. StreamとOptionalの相互運用 ● List<Optional<String>> opts = …; ● opts.stream() .filter(Optional::isPresent) .map(Optional::get) .・・・
  46. 46. StreamとOptionalの相互運用 ● List<Optional<String>> opts = …; ● opts.stream() .flatMap(Optional::stream) .・・・
  47. 47. その他 ● Stream<LocalDate> LocalDate.datesUntil( LocalDate endExclusive) ● Stream<LocalDate> LocalDate.datesUntil( LocalDate endExclusive, Period step) ● Stream<String> Scanner.tokens() ● Stream<MatchResult> Scanner.findAll(Pattern pattern) ● Stream<MatchResult> Matcher.results()
  48. 48. 3位 Javaのバージョン意味不明
  49. 49. いままでのJavaバージョン ● JDK 7 Update 55 – ● JDK 7 Update 60 –
  50. 50. いままでのJavaバージョン ● JDK 7 Update 55 – セキュリティーアップデート(CPU) ● JDK 7 Update 60 – マイナーアップデート ● どちらも同じセキュリティーパッチが入っている
  51. 51. バージョンスキームが変わります ● Java $MAJOR.$MINOR.$SECURITY – Java 9.1.3 ● Java9 ● マイナーバージョンアップ1回 ● セキュリティー3回 ● -$PRE+$BUILD-$OPT – -$PRE: eaとかの情報 – +$BUILD: ビルドナンバー – -$OPT: 追加のビルド情報,日付など
  52. 52. Runtime.Versionクラス Runtime.Version version = Runtime.version(); int major = version.major(); int minor = version.minor(); int security = version.security();
  53. 53. バージョンスキームに依存するコードは 動かなくなるかも! ● System.getProperty("java.version") => "9" ● System.getProperty("java.version").charAt(3) – 例外に!!
  54. 54. 2位 ● ちょっとしたAPIの確認面倒くさい! ● もっと気軽にJava書きたい!
  55. 55. jshell; Java REPL Tool来る! jshell> Runtime.version() $8 ==> 9-ea+122 jshell> $8.major() $9 ==> 9 jshell> $8.minor() $10 ==> 0 jshell> $8.pre() $11 ==> Optional[ea] jshell>
  56. 56. 1位 パッケージ管理イケてない!
  57. 57. クラスパス地獄 public is too public
  58. 58. モジュール化(Jigsaw) // module-info.java module mymodule { requires java.compiler; // java.compilerというモジュールを利用 // java.compilerモジュールファイルで // exportされているパッケージ内のpublicクラスが利用可 exports com.mymodule.util; // com.mymodule.util内のpublicクラスを他モジュールが利用可に }
  59. 59. モジュール化すると・・・? ● クラスパスの指定がほぼ要らなくなる – modulepathを指定する ● ディレクトリ1つだけ ● public classの可視性を管理できる ⇔今まで使用してた内部APIにアクセスできなくなる!?
  60. 60. 他にも ● HTTP2.0 ● Compact Strings ● VarHandle ● G1GCデフォルト化 – CMSがDeprecatedに ● javacの-releaseオプション ● Applet APIがDeprecatedに
  61. 61. More Future ● ローカル変数でvalが! – val hoge = “hoge”; ● ジェネリクスの特殊化 – List<int> ints; ● 値型 – 構造体みたいなの – メモリ使用量削減 ● Foreign Function Interface

×