2018/03/20

JEP では語れない Java SE 10

このエントリーをはてなブックマークに追加

今日リリースされる Java SE 10 の注目機能といえば var の導入ですね。

var の導入などの機能は、OpenJDK の JEP (JDK Enhancement Proposals) で管理されています。たとえば、var の導入は JEP 286 です。

Java SE 10 では 12 の JEP が機能として導入されます。

ところが、JEP になっていない変更といのが、けっこうあるのです。そこで、このエントリーでは、JEP になっていない機能をまとめてみました。

JEP になっていないぐらいなので、かなり細かいです。

 

廃止になった API

Java SE 9 で、@Deprecated アノテーションに forRemoval が追加されました。この値が true なものは、ほんとに削除されることになっています。

Java SE 10 では Java SE 9 で forRemoval = true になったフィールドやメソッドが廃止になっています。いずれも、java.base モジュールに含まれていたものです。

廃止されたフィールド

  • java.lang.SecurityManager.inCheck

SecurityManager クラスの inCheck フィールドは、checkPermission メソッドで置き換えができるので、廃止されました。

廃止されたメソッド

java.lang.Runtime クラス

  • getLocalizedInputStream
  • getLocalizedOutputStream

ローカライズしたストリームを作成するメソッドですが、使うことはまずないと思うので、廃止されても問題ないですよね。

java.lang.SecurityManager クラス

  • classDepth
  • classLoaderDepth
  • currentClassLoader
  • currentLoadedClass
  • getInCheck
  • inClass
  • inClassLoader

これらのメソッドは、いずれも checkPermission メソッドで置き換え可能です。

廃止予定の API

Java SE 10 に含まれる API のうち、将来廃止予定の API は以下の通りです。

これらの API を使用している場合は、なるべく早いうちに変わりの API に置き換えた方がいいです。

廃止予定モジュール

Java EE 系のモジュールは次の Java SE 11 で廃止予定です (JEP 320)。

  • java.activation
  • java.corba
  • java.se.ee
  • java.transaction
  • java.xml.bind
  • java.xml.ws
  • java.xml.ws.annotation

廃止予定のパッケージ

  • java.security.acl

パッケージが廃止される予定なので、java.security.acl パッケージに含まれる Acl インタフェースなどもすべて廃止予定です。

廃止予定のクラス

  • java.lang.Compiler
  • java.security.Certificate
  • java.security.Identity
  • java.security.IdentityScope
  • java.security.Signer
  • javax.security.auth.Policy

廃止予定のフィールド

javax.management.remote.rmi.RMIConnectorServer.CREDENTIAL_TYPES

廃止予定のメソッド

  • java.io.FileInputStream.finalize
  • java.io.FileOutputStream.finalize
  • java.lang.Runtime.runFinalizersOnExit
  • java.lang.Runtime.traceInstructions
  • java.lang.Runtime.traceMethodCalls
  • java.lang.SecurityManager.checkAwtEventQueueAccess
  • java.lang.SecurityManager.checkMemberAccess
  • java.lang.SecurityManager.checkSystemClipboardAccess
  • java.lang.SecurityManager.checkTopLevelWindow
  • java.lang.System.runFinalizersOnExit
  • java.lang.Thread.countStackFrames
  • java.lang.Thread.destroy
  • java.lang.Thread.stop
  • java.util.zip.Deflater.finalize
  • java.util.zip.Inflater.finalize
  • java.util.zip.ZipFile.finalize

 

追加された API

java.base モジュール

java.io.ByteArrayOutputStream クラス

  • toString(Charset charset)

今までキャラクターセットを文字列として指定する toString メソッドはありましたが、Charset オブジェクトで指定できるようになります。

java.io.PrintStream クラス

  • PrintStream(File file, Charset charset)
  • PrintStream(OutputStream out, boolean autoFlush, Charset charset)
  • PrintStream(String fileName, Charset charset)

いずれもコンストラクタで、キャラクターセットを Charset オブジェクトで指定できるようになります。

java.io.PrintWriter クラス

  • PrintWriter(File file, Charset charset)
  • PrintWriter(OutputStream out, boolean autoFlush, Charset charset)
  • PrintWriter(String fileName, Charset charset)

こちらも PrintStream クラスと同様にコンストラクタが追加されました。

java.io.Reader クラス

  • transferTo(Writer out)

リーダーで読み込んだものを直接ライターに書き込めるようになります。

NIO だとできていたので、今さら感はありますけど。

java.lang.Runtime.Version クラス

  • feature()
  • interim()
  • patch()
  • update()

java.lang.StackWalker.StackFrame インタフェース

  • getDescription()
  • getMethodType()

スタックトレース中のメソッドの情報を取得するためのメソッドです。ただ、デフォルトの実装が UnsupportedOperationException 例外を投げるようになっているので、注意が必要です。

StackWalker オブジェクトを作る時に StackWalker.Option.RETAIN_CLASS_REFERENCE を指定しておく必要があります。

java.lang.invoke.MethodType クラス

  • lastParameterType()

java.lang.management.RuntimeMXBean クラス

  • getPid()

java.lang.management.ThreadMXBean クラス

  • dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers, int maxDepth)
  • getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers, int maxDepth)

java.net.URLDecorder クラス

  • decode(String s, Charset charset)

java.net.URLEncoder クラス

  • encode(String s, Charset charset)

URLDecoder クラスも URLEncoder クラスも Charset クラスを指定できるようになっています。

java.nio.channels.Channels クラス

  • newReader(ReadableByteChannel ch, Charset charset)
  • newWritter(WritableByteChannel ch, Charset charset)

こちらも同じですね。

java.nio.file.FileStore クラス

  • getBlockSize()

java.time.chrono.HijirahEra 列挙型

java.time.chrono.MinguoEra 列挙型

java.time.chrono.ThaiBuddhistEra 列挙型

  • getDisplayName(TextStyle style, Locale locale)

getDisplayName メソッドは Era インタフェースでデフォルトメソッドとして実装されていましたが、それぞれのクラスでオーバーライドされています。

java.time.format.DateTimeFormatter クラス

  • localizedBy(Locale locale)

ロケールに応じた DateTimeFormatter オブジェクトのコピーを返します。

java.util.DoubleSummaryStatistics クラス

  • DoubleSummaryStatistics(long count, double min, double max, double sam)

java.util.IntSummaryStatistics クラス

  • IntSummaryStatistics(long count, int min, int max, long sum)

java.util.LongSummaryStatistics クラス

  • LongSummaryStatistics(Long count, long min, long max, long sum)

なんたら Statistics クラスは空のオブジェクトを作って、accept メソッドをコールすることによって最小、最大、平均などを求めていたのですが、はじめからそれらの値をセットして作ることができるようになりました。

java.util.Formatter クラス

  • Formatter(File file, Charset charset, Locale l)
  • Formatter(OutputStream os, Charset charset, Locale l)
  • Formatter(String fileName, Charset charset, Locale l)

java.util.Scanner クラス

  • Scanner(File source, Charset charset)
  • Scanner(InputStream source, Charset charset)
  • Scanner(ReadabbleByteChannel source, Charset charset)
  • Scanner(Path source, Charset charset)

Formatter クラスも Scanner クラスも、Charset が指定できるようになっています。というか、Charset を指定できるようになる変更が多すぎ。

java.util.List インタフェース

  • copyOf(Collection<? extends E> coll)

java.util.Set インタフェース

  • copyOf(Collection<? extends E> coll)

java.util.Map インタフェース

  • copyOf(Map<? extends K, ? extends V> map)

引数のコレクションをコピーして、変更不可なリストもしくはセットを作ることができます。いずれも static メソッドです。

ただし、引数で指定するコレクションが変更不可な場合、コピーは作られずに、引数で指定したコレクションをそのまま返します。

java.util.Optional クラス

  • orElseThrow()

java.util.OptionalDouble クラス

  • orElseThrow()

java.util.OptionalInt クラス

  • orElseThrow()

java.util.OptionalLong クラス

  • orElseThrow()

値がある場合は値を返し、値がない場合は NoSuchElementException 例外を投げます。

java.util.SplittableRandom クラス

  • nextBytes(byte[] bytes)

引数で指定した配列に乱数をセットします。

java.util.concurrent.FutureTask クラス

  • toString()

タスクを表す文字列だけでなく、タスクの状態も加えて返します。

java.util.concurrent.locks.StampedLock クラス

  • isLockStamp(long stamp)
  • isOptimisticReadStamp(long stamp)
  • isReadLockStamp(log stamp)
  • isWriteLockStamp(log stamp)

いずれも static メソッドで、引数で指定したスタンプの状態を調べるために使用します。

java.util.jar.JarEntry クラス

  • getRealName()

java.util.jar.JarFile クラス

  • versionedStream()

Java SE 9で導入されたマルチリリース Jar ファイルで、バージョンごとの JarEntry オブジェクトをストリームとして返します。

java.tuil.spi.LocaleNameProvider クラス

  • getUnicodeExtensionKey(String key, Locale locale)
  • getUnicodeExtensionType(String type, String key, Locale locale)

java.util.stream.Collectors クラス

  • toUnmodifiableList()
  • toUnmodifiableSet()
  • toUnmodifiableMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper)
  • toUnmodifiableMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction)

ストリーム処理の返り値として、変更不可のコレクションを返すための Collectors メソッドです。

java.compiler モジュール

javax.lang.model.SourceVersion 列挙型

  • RELEASE_10

javax.lang.model.util.TypeKindVisitor6 クラス

  • visitNoTypeAsModule(NoType t, P p)

javax.lang.model.util.TypeKindVisitor9 クラス

  • visitNoTypeAsModule(NoType t, P p)

java.management.rmi モジュール

javax.management.remote.rmi.RMIConnectorServer クラス

  • CREDENTIALS_FILTER_PATTERN
  • SERIAL_FILTER_PATTERN

java.desktop モジュール

java.awt.Toolkit クラス

  • getMenuShortcutKeyMaskEx()

getMenuShortcutKeyMask メソッドが Deprecated になったので、その代わりとなるメソッドです。

getMenuShortcutKeyMask メソッドはデフォルトで、Event.CTRL_MASK を返していたのですが、マスクとしては不適切だということらしいです。getMenuShortcutKeyMaskEx メソッドでは InputEvent.CTRL_DOWN_MASK をデフォルトで返すようになってます。

java.awt.geom.Path2D クラス

  • trimToSize()

java.awt.geom.Path2D.Float クラス

  • trimToSize()

java.awt.geom.Path2D.Double クラス

  • trimToSize()

容量削減のためのメソッドです。

javax.swing.ButtonModel インタフェース

  • getGroup()

ボタンがラジオボタンの場合、そのグループを返します。ラジオボタン以外は null を返します。

javax.swing.plaf.basic.BasicMenuUI クラス

  • getMinimumSize(JComponent c)

メニューの項目に使用するため、引数で指定されたコンポーネントの最小のサイズを返します。

結構あると思うか、メジャーバージョンアップの割には少ないと思うかは、自由です。半年でのリリースだと思うと、多いと思うかもしれません。

ほんとは、もう 1 つ、とある例外のコンストラクタが追加されているのですが、まぁいいでしょう。

2017/06/03

Oracle Code Japan Tour

このエントリーをはてなブックマークに追加

今年も Stephen Chin さんと Sebastian Daschner さんはオートバイに乗って日本各地の JUG を回っているのです。

去年は Nighthacking Tour でしたけど、今年は Oracle Code Tour。

でも、去年は沖縄と札幌だけは飛行機だったのです。どうやら、Steve たちは、沖縄はともかく、札幌にバイクで行けなかったことを悔やんでいたらしいです。

で、今年はすべての行程をバイク。札幌もバイクでした。

全行程を示すと...

東京 - 名古屋 - 大阪 - 岡山 - 広島 - 熊本 - 福岡 - 福井 - 仙台 - 札幌

だそうです。セミナはありませんでしたけど、四国にも彼らはいっていたようです。

櫻庭は去年と同じく、週末だけのスポット参戦。広島札幌で登壇させてもらいました。

広島で講演するのは 2013 年以来。@soudai1025 さんに誘われてオープンセミナー広島に登壇したのでした。その時は Java SE 8 について話したのですが、今回は Java SE 9。

札幌は去年の Night Hacking Tour でも講演させていただいたので、2 年連続。

去年は大韓航空機が羽田で事故を起こしたせいで、札幌に来るまでが大変でした。今年はそんなトラブルもなく、無事に講演することができました。

両方とも内容は Java SE 9 です。Java Day Tokyo の資料を日本語にして、Jigsaw と JShell をくっつけています。

広島と札幌では微妙に資料が違うのですが、それらを統合したものを slideshare にアップしてあります。

2017/05/20

JJUG CCC 2017 Spring

このエントリーをはてなブックマークに追加

Java Day Tokyo の後は、CCC です。前回の秋は出なかったので、1 年ぶり。

今回は、Project Jigsaw です。

しかし、今月になって Jigsaw の JSR 376Public Review Ballot が否決されてしまうと波乱があったばかり。こんな状態で、なんの話をすればいいのでしょう?

Ballot の意見を見ていても、結局は過去とのマイグレーションをどうすればよいかという点が指摘されています。OpenJDK の Jigsaw の ML でも、マイグレーション関連について活発に議論されています。

しかし、このあたりのことは Java Day Tokyo でのキーノートや Jigsaw のセッションでは一切触れられていませんでした。

そこで、このセッションでは発表時点で分かっていることはなるべく盛り込んで、話をしています。しかし、セッション後にやはり変更された点や追加議論が必要とされている項目も出てきています。

そういう点については、また稿をあらためて紹介できればと思っています。6 月の Public Review Reconsideration Ballot の後ですかね。

さて、発表資料はこちら。

すでに、ほぼ確定の module-info.java の書き方や、ビルド/実行の方法などについて触れた後、残りの 1/3 の時間を使ってマイグレーションについて話をしました。

特に既存の JAR ファイルをモジュールとして扱う Automatic Module について紹介しました。しかし、その Automatic Module が JCP での議論のトピックになっているわけです。とりあえず、セッションでは改定案を紹介しましたが、最終案がこうなるとはかぎりません。

あっ、1 点だけ、セッションで失敗したと思ったことが...

標準で提供されている Platform Module を調べるために java コマンドに --list-modules オプションがあります。これで調べた結果を示したのですが、JRE の java コマンドを使ってしまいました ><

JDK の java コマンドと JRE の java コマンドだと使えるモジュールも異なるのです。たとえば、jdk.jshell などは JDK の java コマンドだけです (もちろん、JRE でも --add-modules すれば使えます)。その点をすっかり忘れて、JRE でやってしまったのでした。

 

このセッションでは質問を受け付けるために sli.do というサービスを使いました。

Java Day Tokyo で @bitter_fox さんが、このサービスを使っていたので、私もまねしてみたわけです。

セッション中にオンラインで質問を投げられるし、それに対して「いいね」をすることもできます。なかなかいいですね、これ。次回も使ってみよう!!

というわけで、セッション中にいただいた質問をここで答えておきます。

 

Q. JASRACのひとがやってくる危険が危なくないですかww?

A. あー、あー、聞こえない、聞こえない

Q. mavenでは、moduleとどうやって整合とるのでしょう

A. Maven の動きをあまり追いかけていないのですが、問題となるのは Jigsaw のモジュールと artifacts が違うものだというこということにあると思います。どうやって折り合いをつけるかということは、まだ決まっていないようです。

プレゼンテーションにも登場させた Stephen Colebourne がこの件についてブログで言及しているので、ご参考までに。

Java SE 9 - JPMS modules are not artifacts

Q. メタ情報なのに.javaっていうのがちょっと嫌。JSONじゃダメなんだろうか。

A. Java で JSON を扱うのは意外に面倒なので... module-info.java を扱うのは javac なので、Java の構文解析がそのまま使えるのがいいのではないでしょうか。

プレゼン中にも言及しましたが、JSON-B が Java SE でも使えるようになったら変わるかもしれません。あくまでも個人的な意見ですが。

Q. moduleやrequires, exportsなどのキーワードはmodule-info.javaでのみ有効な予約語?の位置づけでしょうか

A. module-info.java のみで使用できる予約語です。

Q. モジュール化した場合としない場合でアプリの起動時間にどのくらい差がでてきますか?

A. 大きいシステムでモジュールを多くロードするようなシステムであれば差がでると思いますが、私自身は試してないのでよく分かりません。小さいシステムだと、それほど差がないように感じます。しかし、計測を行ったわけではないので、あくまでも感想レベルだと思ってください。

Q. module-info.javaが小文字始まりになった理由は何かあるのでしょうか

A. パッケージの情報を記述する package-info にならったのだと思います。

Q. // puckage export typo?

A. タイポはなかなか気がつかないので、ご指摘ありがとうございます! 公開している資料では修正してあります。

Q. モジュール版のmavenセントラルができることになるんですか?

A. 今のところそのような予定はないです。個人的には Maven セントラルが利用できれば一番いいのではないかと考えていますが、そのためには前述した artifacts とモジュールのすり合わせを行う必要があります。まだ、道は遠そうです。

Q. 昔、jarの中にjarを入れるsuper packageみたいな話があった気がしますが、そっちの話はどうなったのでしよう

A. JAR をまとめたパッケージングに関しては JSR 277 で JAM (Java Archive Module) というのが提案されていましたが、棄却されています。super package は言語側の拡張提案で、JSR 294 で提案されていましたが、こちらも棄却されました。これらを受け継いだのが、Project Jigsaw になります。

Q. Jigsawにはバージョンを管理する仕組みはないのでしようか? モジュール名にバージョン番号を入れる?

A. バージョンをつけることは可能です。バージョンをつけるには、jar コマンドの --module-version オプションで記述します。ただし、そのバージョンを使用して、バージョンを指定してビルドするなどは、現状ではサポートされていません。

Q. exportsで指定したパッケージのサブパッケージは公開されるのでしょうか?

A. 公開されません。公開するにはサブパッケージも exports 文を記述する必要があります。

Q. MANIFEST.MF に名前がなかったらどうするのでしょう

A. ファイル名が使われると思いますが、確認はしていません。

Q. testだけでパッケージを公開(exports, opens)したい場合やmoduleをrequiresしたい場合はどうするのが良いのでしょうか?

A. これは非常に難しい問題で、現状 Jigsaw では同じパッケージを複数のモジュールに分割することはできません。そのため、ファイルツリーを src と test に分割している (ビルドしたクラスファイルも別ディレクトリ) 場合はモジュールにしてしまうと、テストを実行することができません。

櫻庭もこれに対する最適解を見つけている最中なのですが、現状はテストの時はモジュールとして扱わないようにしています。コンパイルや実行に他のモジュールが必要な場合、--module-path と --add-modules オプションを使用して必要なモジュールをロードするようにしています。