mike-neckのブログ

Java or Groovy or Swift or Golang

Gradle3におけるJavaプロジェクトのビルド入門(3) -- 用語の再確認とJigsawとの関連 #gradle

f:id:mike_neck:20151108133321p:plain

今回はJVM component modelにおける用語について整理しておく。


前回、前々回とGradle3におけるJavaプロジェクトのビルドにおけるJVM component modelの入門を行っていった。

mike-neck.hatenadiary.com

mike-neck.hatenadiary.com

また、JVM component modelに関連する知識としてJigsawについて簡単なまとめを行った。

mike-neck.hatenadiary.com

以上のエントリーの中で、僕は公式の(ただし今後変更される可能性のある)用語を幾つか混同していたので、それらをまとめておきたいと思う。また、公式のリンクは今後のリリースにともなって変更される可能性があるので、注意されたい。


用語

まず、基本的な用語を抑えておく

コンポーネント(component)

A component is a general concept for a piece of software that might be deliverable. Example of components are a standalone application, a web application, a library, etc. A component is often composed of other components.

コンポーネントは配布可能なソフトウェアの一部分を意味する。コンポーネントの例としてはスタンドアローンアプリケーション、ウェッブアプリケーション、一般的にライブラリーと呼ばれるものなどである。コンポーネントは他のコンポーネントとともに構成される。

以上が定義である。したがって、プロジェクトで成果物として作成されるものとして指定されるのがコンポーネントとなる。

ライブラリー(library)

A library is a buildable component. In the Java world, a library is often assimilated to a Jar file, but while a Jar file represents an output, a library is the description of how the output is build. A library is defined by the combination of its source sets and variants.

ライブラリーはビルド可能なコンポーネントである。一般的にライブラリーはjarファイルと同等視されている。しかしGradle3ではjarファイルは単なる出力であり、ライブラリーは成果物のビルド方法の定義である。ライブラリーは後に説明するソースセットとバリアントの組み合わせによって定義される。

ソースセット(source set)

A source set represents a logical group of source files in a component. Ass such, a source set is often an input to a single compilation task, which will produce an output(classes, compiled CSS, etc). A library may consist of multiple source sets.

ソースセットが表すのはコンポーネント内部のソースファイルの論理的グループである。したがって、ソースセットは一つのコンパイルタスクの入力である。なお、コンパイルタスクは出力(クラスファイルやコンパイルされたCSSなど)を生成する。ライブラリーは複数のソースセットで構成される。

バリアント(variant)

A variant represents a modulation of a component. A library, for example, might target Java 6 and Java 7, effectively producing two distinct outputs: a Java 6 jar and a Java 7 jar. In this case, the target platform is an example of a variant dimension. Custom library types may define their own variant dimensions, which will participate in dependency resolution.

バリアントが表すのはコンポーネントの種類である。ライブラリーは、例えば、Java6およびJava7を対象としており、結果として二つの異なる出力を生成する。Java6用のjarとJava7用のjarである。この例では対象プラットフォームのバリアント値を表している。ライブラリーによっては異なるバリアント値を取ることがあり、その値は依存性解決に利用されることがある。

バイナリー(binary)

A binary represents the output of a library. Given a combination of variants, a library may produce multiple binaries. A binary is often a consumable artifact of other components.

バイナリーはライブラリーの出力を表す。バリアントの組み合わせによってはライブラリーは複数のバイナリーを生成する。バイナリーは他のコンポーネントによって利用される成果物である。


また、基本的な用語に加え、次の一般的にも用いられている用語も利用する

API

  • An API is a set of classes, interfaces, methods that are exposed to a consumer.
  • APIはクラス、インターフェース、メソッドなどの集合であり、利用者に公開するものである
  • An API specification is the specification of classes, interfaces or methods that belong to an API. It can be found in various forms, like module-info.java in Jigsaw, or the api{...} block that Gradle defines as part of those stories. Usually, we can simplify this to a list of packages, called exported packages.
  • API仕様はAPIに含まれているクラス、インターフェース、メソッドの仕様である。これは様々な方法で定義されうる。Jigsawであればmodule-info.javaにて定義する。一方Gradleではapi{}ブロックを利用する。通常、公開パッケージというパッケージのリストを指定することで簡略化する。
  • A runtime jar consists of API classes and non-API classes used at execution time. There can be multiple runtime jars depending on combinations of the variant dimensions: target platform, hardware infrastructure, target application server, ...
  • ランタイムjarはAPIクラスと実行時にのみ使われる非APIクラスによって構成される。バリアント値にの組み合わせによっては複数のランタイムjarが存在しうる。ターゲットプラットフォーム、ハードウェア構成、ターゲットアプリケーションサーバーなど
  • API classes are classes of a variant which match the API specification
  • APIクラスはAPI仕様に一致するクラスである
  • Non-API classes are classes of a variant which do not match the API Specification. They can be referred to as internal classes.
  • APIクラスはAPI仕様に一致しないクラスである。内部クラスとして参照されるクラスである。
  • A stubbed API class is an API class for which its implementation and non public members have been removed. It is meant to be used when a consumer is going to be compiled against an API.
  • スタブAPIクラスはAPIクラスであり、その実装クラスおよび非publicメンバーを取り除いたクラスである。これは利用者がAPIを用いてコンパイルを行い際に用いられる。
  • An API jar is a collection of API classes. There can be multiple API jars depending on the combinations of variant dimensions.
  • API jarはAPIクラスを集めたものである。バリアント値の組み合わせにより複数API jarが存在しうる。
  • A stubbed API jar is a collection of stubbed API classes. There can be multiple stubbed API jars depending on the combinations of variant dimensions.
  • スタブAPI jarはスタブAPIクラスを集めたものである。バリアント値の組み合わせにより複数API jarが存在しうる。
  • An ABI(application binary interface) corresponds to the public signature of an API, that is to say the set of stubbed API classes that it exposes(and their API visible members).
  • ABI(アプリケーション・バイナリー・インターフェース)はAPIの公開署名にも対応している。つまり、公開されたスタブAPIクラスである。

Jigsawとの関連

次にJigsawとの関連を引用し、Jigsawの用語とJVM component modelの用語の対応を確認したい。

Gradleの公式ドキュメントでJigsawへの言及があるのは70.10 Enforcing API boundaries at compile time(API境界の強制をコンパイル時に行う)である。

Often a library will contain many types that -- despite having public visibility -- are intended for internal use only within that library. JDK 9 will introduce Jigsaw, the reference implementation of the Java Module System, which will provide both compile-time and run-time enforcement of strong encapusulation at the library (aka: module) level. This means that packages not intended for public consumption can remain private to the library, regardless whether the types within those packages have public visibility.

Gradle anticipates the arrival of JDK 9 and the Java Module System with an approach to specifying and enforcing strong encapsulation at compile-time. However, users need not wait for the arrival of JDK 9 to use it; this feature can be used on any version of the Java platform that Gradle supports.

--たとえアクセス修飾子がpublicであるにもかかわらず--ライブラリー内部だけでのみ使うように意図された型がライブラリーに含まれることはよくある。JDK 9が導入するJigsawは、Javaモジュールシステムの参照実装であるが、コンパイル時および実行時に強いカプセル化をライブラリー(モジュールとして知られている)に提供する。これによって、利用者に使われたくないパッケージ、たとえpublicにアクセス可能なパッケージであっても、それをライブラリー内だけで使えるようにすることができる。

GradleではJDK 9および、コンパイル時に強いカプセル化をおこなうアプローチのJavaモジュールシステムの到来を予想している。もちろんユーザーはJDK9のリリースを待つ必要はない。この機能(コンパイル時に強いカプセル化をおこなうこと)はGradleがサポートするすべてのJavaプラットフォームで利用できる。

ここで「強いカプセル化をライブラリー(モジュールとして知られている)」に着目すると、Gradle3のJVM component modelとJigsawの関係性が見えてくるようになる。

- Gradle Jigsaw
コンパイルの単位 library module
公開パッケージの指定 api{}ブロックでのexports(String)メソッド exports パッケージ名
依存ライブラリ(モジュール)の指定 api.dependencies{}ブロックでのlibrary(String)メソッド requires パッケージ名
推移的依存ライブラリ(モジュール)の指定 なし(すべて依存ライブラリーに推移的依存が適用される) requires public パッケージ名
サービスローダー なし ユーザーモジュール : uses FQCN名
提供モジュール : provides FQCN名 with FQCN(実装)名
リンカー なし jlinkコマンド
ソースセット java{}ブロックのsourceSet{}ブロックで指定 概念がない
バリアント targetPlatform(String)メソッド 概念がないし、Java9固定

かなり中途半端な終わり方になるが、Gradle3 JVM component modelによるビルドとJigsawの関連が少し見えてきたのではないかと思う。また、自己中心的な考えだが、Gradleでの用語の確認ができたところが心強い。

次回は同一のプロジェクトをJigsawとGradle(2.9)とでビルドしてみたいと思う。

おわり