Java 9の新機能

1概要

Java 9には豊富な機能セットが付属しています。新しい言語の概念はありませんが、新しいAPIと診断コマンドは開発者にとって間違いなくおもしろいでしょう。

今回の記事では、いくつかの新機能について簡単に概要を説明します。新機能の完全なリストはhttp://openjdk.java.net/projects/jdk9/[ここ]にあります。

** 2モジュラーシステム - ジグソープロジェクト

大きなものから始めましょう - Javaプラットフォームにモジュール性をもたらします。

モジュラーシステムは、OSGiフレームワークのシステムと同様の機能を提供します。モジュールは依存関係の概念を持ち、パブリックAPIをエクスポートし、実装の詳細を非表示/非公開にすることができます。

ここでの主な動機の1つは、利用可能なメモリがはるかに少ないデバイスで実行できるモジュール式JVMを提供することです。 JVMは、アプリケーションに必要なモジュールとAPIだけで実行できます。これらのモジュールが何であるかの説明についてはhttp://cr.openjdk.java.net/~mr/jigsaw/ea/module-summary.html[このリンク]をチェックしてください。

また、 com.sun。** などのJVM内部(実装)APIは、アプリケーションコードからアクセスできなくなりました。

簡単に言うと、モジュールはjavaコード階層の最上位にある module-info.java というファイルに記述されます。

module com.baeldung.java9.modules.car {
    requires com.baeldung.java9.modules.engines;
    exports com.baeldung.java9.modules.car.handling;
}

私たちのモジュール car はモジュール engine handling 用のパッケージを実行してエクスポートすることを要求します。

より詳しい例については、OpenJDK http://openjdk.java.net/projects/jigsaw/quick-start [Project Jigsaw:

モジュールシステムクイックスタートガイド]。

3新しいHTTPクライアント

待望の古い HttpURLConnection の置き換え。

  • 新しいAPIは java.net.http パッケージの下にあります。

これはhttps://http2.github.io/[HTTP/2 protocol]とhttps://en.wikipedia.org/wiki/WebSocket[WebSocket]の両方のハンドシェイクをサポートするはずです。/hc.apache.org/httpcomponents-client-ga/[Apache HttpClient]、http://netty.io[Netty]、およびhttp://eclipse.org/jetty[Jetty]。

単純なHTTPリクエストを作成して送信することによって、この新しい機能を見てみましょう。

  • 更新:http://openjdk.java.net/jeps/110[HTTP Client JEP]はIncubatorモジュールに移動されているので、 java.net.http パッケージには含まれておらず、代わりに jdkの下で利用可能です。 incubator.http . **

3.1. クイックGETリクエスト

このAPIはBuilderパターンを使用しているため、すばやく簡単に使用できます。

HttpRequest request = HttpRequest.newBuilder()
  .uri(new URI("https://postman-echo.com/get"))
  .GET()
  .build();

HttpResponse<String> response = HttpClient.newHttpClient()
  .send(request, HttpResponse.BodyHandler.asString());

4プロセスAPI

オペレーティングシステムプロセスを制御および管理するためのプロセスAPIが改善されました。

4.1. プロセス情報

クラスjava.lang.ProcessHandle __には、新しい機能のほとんどが含まれています。

ProcessHandle self = ProcessHandle.current();
long PID = self.getPid();
ProcessHandle.Info procInfo = self.info();

Optional<String[]> args = procInfo.arguments();
Optional<String> cmd =  procInfo.commandLine();
Optional<Instant> startTime = procInfo.startInstant();
Optional<Duration> cpuUsage = procInfo.totalCpuDuration();

current メソッドは、現在実行中のJVMのプロセスを表すオブジェクトを返します。 Info サブクラスはプロセスに関する詳細を提供します。

4.2. 破壊プロセス

それでは、 destroy() を使って、実行中のすべての子プロセスを停止しましょう。

childProc = ProcessHandle.current().children();
childProc.forEach(procHandle -> {
    assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
});

5小さな言語の修正

5.1. リソースを使ってみる

Java 7では、 try-with-resources 構文では、ステートメントによって管理されている各リソースに対して新しい変数を宣言する必要があります。

Java 9では、さらに洗練された機能があります。リソースが最終または実質的に最終の変数によって参照される場合、try-with-resourcesステートメントは新しい変数が宣言されずにリソースを管理できます。

MyAutoCloseable mac = new MyAutoCloseable();
try (mac) {
   //do some stuff with mac
}

try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
  //do some stuff with finalCloseable
} catch (Exception ex) { }

5.2. ダイヤモンドオペレーターエクステンション

これで、匿名内部クラスと組み合わせてdiamond演算子を使用できます。

FooClass<Integer> fc = new FooClass<>(1) {//anonymous inner class
};

FooClass<? extends Integer> fc0 = new FooClass<>(1) {
   //anonymous inner class
};

FooClass<?> fc1 = new FooClass<>(1) {//anonymous inner class
};

5.3. インターフェースプライベートメソッド

今後のJVMバージョンのインタフェースには private メソッドを含めることができます。これを使用して、長いデフォルトメソッドを分割できます。

interface InterfaceWithPrivateMethods {

    private static String staticPrivate() {
        return "static private";
    }

    private String instancePrivate() {
        return "instance private";
    }

    default void check() {
        String result = staticPrivate();
        InterfaceWithPrivateMethods pvt = new InterfaceWithPrivateMethods() {
           //anonymous class
        };
        result = pvt.instancePrivate();
    }
}}

6. JShellコマンドラインツール

JShellはread-eval-printループです - 略してREPLです。

簡単に言えば、それはAPIと共にJavaの宣言、ステートメント、および式を評価するための対話型ツールです。 main メソッドを使用して新しいクラスを作成する必要がある小さなコードスニペットをテストするのに非常に便利です。

jshell 実行可能ファイル自体は、 <JAVA HOME>/bin__フォルダーにあります。

jdk-9\bin>jshell.exe
|  Welcome to JShell -- Version 9
|  For an introduction type:/help intro
jshell> "This is my long string. I want a part of it".substring(8,19);
$5 ==> "my long string"

対話型シェルには履歴と自動補完機能があります。ファイルへの保存やファイルからのロード、すべてまたは一部の記述ステートメントなどの機能も提供します。

jshell>/save c:\develop\JShell__hello__world.txt
jshell>/open c:\develop\JShell__hello__world.txt
Hello JShell!

コードスニペットはファイルのロード時に実行されます。

7. JCMDサブコマンド

jcmd コマンドラインユーティリティの新しいサブコマンドについて調べてみましょう。 JVMにロードされているすべてのクラスとその継承構造のリストを取得します。

以下の例では、Eclipse Neonを実行しているJVMにロードされた java.lang.Socket の階層がわかります。

jdk-9\bin>jcmd 14056 VM.class__hierarchy -i -s java.net.Socket
14056:
java.lang.Object/null
|--java.net.Socket/null
|  implements java.io.Closeable/null (declared intf)
|  implements java.lang.AutoCloseable/null (inherited intf)
|  |--org.eclipse.ecf.internal.provider.filetransfer.httpclient4.CloseMonitoringSocket
|  |  implements java.lang.AutoCloseable/null (inherited intf)
|  |  implements java.io.Closeable/null (inherited intf)
|  |--javax.net.ssl.SSLSocket/null
|  |  implements java.lang.AutoCloseable/null (inherited intf)
|  |  implements java.io.Closeable/null (inherited intf)

jcmd commandの最初のパラメーターは、コマンドを実行したいJVMのプロセスID(PID)です。

もう1つの興味深いサブコマンドは set vmflag__です。 JVMプロセスを再起動して起動パラメータを変更することなく、JVMパラメータをオンラインで変更できます。

サブコマンド jcmd 14056 VM.flags -all を使用して、使用可能なすべてのVMフラグを見つけることができます。

8高解像度画像API

インタフェース java.awt.image.MultiResolutionImage は、解像度が異なる一連の画像を単一のオブジェクトにカプセル化します。与えられたDPIメトリックと一連の画像変換に基づいて解像度固有の画像バリアントを取得することも、画像内のすべてのバリアントを取得することもできます。

java.awt.Graphics クラスは、現在の表示DPIメトリックと適用されている変換に基づいて、マルチ解像度画像からバリアントを取得します。

クラス java.awt.image.BaseMultiResolutionImage は、基本的な実装を提供します。

BufferedImage[]resolutionVariants = ....
MultiResolutionImage bmrImage
  = new BaseMultiResolutionImage(baseIndex, resolutionVariants);
Image testRVImage = bmrImage.getResolutionVariant(16, 16);
assertSame("Images should be the same", testRVImage, resolutionVariants[3]);

9可変ハンドル

APIは java.lang.invoke の下にあり、 VarHandle MethodHandles で構成されています。オブジェクトフィールドおよび配列要素に対して、 java.util.concurrent.atomic および sun.misc.Unsafe 操作と同等のパフォーマンスを提供します。

  • Java 9 Modularシステムでは、 sun.misc.Unsafe へのアプリケーションコードからのアクセスはできません。

10発行 - 購読フレームワーク

クラス java.util.concurrent.Flow は、http://www.reactive-streams.org/[Reactive Streams]publish-subscribeフレームワークをサポートするインタフェースを提供します。これらのインタフェースは、JVM上で実行されている多数の非同期システムにわたる相互運用性をサポートしています。

カスタムコンポーネントを作成するには、ユーティリティクラス SubmissionPublisher を使用できます。

11統合JVMロギング

この機能は、JVMのすべてのコンポーネントに共通のロギングシステムを導入します。ロギングを実行するためのインフラストラクチャを提供しますが、すべてのJVMコンポーネントからの実際のロギング呼び出しを追加するわけではありません。 JDKのJavaコードへのロギングも追加されません。

ロギングフレームワークは、 gc compiler threads など、 tags のセットを定義します。起動時にロギングを有効にするには、コマンドラインパラメータ -Xlog を使用します。

「debug」レベルを使用して「gc」タグでタグ付けされたメッセージを、装飾なしで「gc.txt」というファイルに記録します。

java -Xlog:gc=debug:file=gc.txt:none ...

-Xlog:help は可能なオプションと例を出力します。ロギング設定は jcmd コマンドを使用して実行時に変更できます。 GCログをinfoに設定してファイルにリダイレクトします - gc__logs:

jcmd 9615 VM.log output=gc__logs what=gc

12. 新しいAPI

12.1. 不変セット

java.util.Set.of() - 与えられた要素の不変な集合を作成します。 Java 8では、複数の要素のセットを作成するには、複数行のコードが必要です。これで、次のように簡単に実行できます。

Set<String> strKeySet = Set.of("key1", "key2", "key3");

このメソッドによって返される Set はJVMの内部クラスです。

public java.util.AbstractSet を拡張する java.util.ImmutableCollections.SetN 。不変です - 要素を追加または削除しようとすると、 UnsupportedOperationException がスローされます。

同じ方法で配列全体を Set に変換することもできます。

12.2. ストリーミングのオプション

java.util.Optional.stream() を使用すると、オプション要素でStreamsの機能を簡単に使用できます。

List<String> filteredList = listOfOptionals.stream()
  .flatMap(Optional::stream)
  .collect(Collectors.toList());

13. 結論

Java 9には、モジュール式のJVMと、その他多数の新しく多様な改善と機能が付属します。

GitHubで利用可能 の例のソースコードを見つけることができます。