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で利用可能

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