原文はこちら。
The original entry was written by Dustin Marx.
http://marxsoftware.blogspot.com/2020/09/inline-classes-jep-390.html
JEP 390 (“Warnings for Value-Based Classes”) は実際の内容(inlineクラスへの進展)よりも、その内容(inlineクラスになる可能性のある@ValueBased
アノテーションが付いたJDK クラスの「インスタンス上での不適切な同期の試行」に関するアノテーションと警告)の方が刺激的な JEP (JDK Enhancement Proposal) です。
JEP 390: Warnings for Value-Based Classes
https://openjdk.java.net/jeps/390
"Value-based Classes"
(値ベース・クラス)という用語はJava SE 8のJavadocに含まれていました。
値ベース・クラス / Value-based Classes
https://docs.oracle.com/javase/jp/8/docs/api/java/lang/doc-files/ValueBased.html
https://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html
そのなかで、当時値ベース・クラスの特徴として以下のものがあげられていました。
- finalかつ不変(ただし、可変オブジェクトへの参照を含むことができる)。
equals
、hashCode
、およびtoString
の実装を持つ(インスタンスの状態からのみ計算される、識別情報あるいは他のオブジェクトまたは変数の状態からは計算されない)- インスタンス間の参照等価性(
==
)、インスタンスのIDハッシュ・コード、またはインスタンスの固有ロックでの同期など、ID依存操作を使用しない。 - 参照等価性(
==
)ではなくequals()
のみに基づいて同等と見なされる。 - アクセス可能コンストラクタを持たない。かわりに、返されるインスタンスの識別情報についてコミットしないファクトリ・メソッドによってインスタンス化される。
- 同等のときに自由に置換可能。つまり、計算またはメソッド呼び出しで
equals()
に基づいて等しい任意の2つのインスタンスx
とy
を交換しても、動作の表面上の変化は起きない。
Javadocでは、以下のような警告も記載しています。
A program may produce unpredictable results if it attempts to distinguish two references to equal values of a value-based class, whether directly via reference equality or indirectly via an appeal to synchronization, identity hashing, serialization, or any other identity-sensitive mechanism. Use of such identity-sensitive operations on instances of value-based classes may have unpredictable effects and should be avoided.
値ベース・クラス / Value-based Classes
プログラムは、値ベース・クラスの同等の値に対する2つの参照を区別しようとした場合、参照等価性に基づいて直接的に、あるいは同期、IDハッシュ、直列化、または他のID依存メカニズムに基づいて間接的に、のどちらの場合でも、予期できない結果を生成する可能性があります。こうしたID依存操作を値ベース・クラスのインスタンスで使用すると、予測できない影響が生じることがあるため、回避するようにしてください。
https://docs.oracle.com/javase/jp/8/docs/api/java/lang/doc-files/ValueBased.html
https://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html
このJavadocはJava 15でも基本的に同じで、ある特定されたクラスのJavadocコメントにリンクされています。
値ベース・クラス / Value-based Classes
https://docs.oracle.com/javase/jp/15/docs/api/java.base/java/lang/doc-files/ValueBased.html
https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/doc-files/ValueBased.html
値ベース・クラスを知るのであれば、Nicolai Parlogのブログエントリがよいでしょう。
Value-Based Classes
https://nipafx.dev/java-value-based-classes/
あるJDKクラスがJava 8以後、Javadocで値ベース・クラスと特定されていますが、JEP 390の目的は @ValueBased
というアノテーションをこうしたタイプのクラスのために提供することにあります。このアノテーションはコメントよりも強力なコンストラクトであり、具体的には “warnings about improper attempts to synchronize on instances of such classes”(こうしたクラスのインスタンスでの不適切な同期の試行に関する警告)と共に使うことを意図しています。このアノテーションの利点は、ある日、コード内で同期化に適さないクラスのインスタンスで同期しようとしている使い方に対し、開発者に警告を与えることができるということです。この警告が利用できるようになってから、実際に @ValueBased
アノテーションが付いたクラスがinlineクラスに転換するまでにはかなりの時間がかかるはず(JEPではこれを「移行が起こる前の数回のリリース」と表現しています)なので、開発者が同期を適用するクラスを変更する機会は十分にあるでしょう。
同期のためのJDKクラスの使用に関する警告は、それ自体にメリットがあります。さらに、このJEPはinline型へのワクワクするような一歩だと思いますし、inline型についての詳細がこのJEPには詰まっています。具体的には、JEP 390のMotivation(動機)の第1段落には次のように書かれています。
The Valhalla Project is pursuing a significant enhancement to the Java programming model in the form of inline classes. Such classes declare their instances to be identity-free and capable of inline or flattened representations, where instances can be copied freely between memory locations and encoded using solely the values of the instances’ fields.(Project Valhallaは、inlineクラスの形でJavaプログラミング・モデルを大幅に強化することを追求している。このようなクラスは、インスタンスにはIDがなく、inlineまたはフラットな表現が可能であることを宣言する。inlineクラスの場合、インスタンスをメモリロケーション間で自由にコピーし、インスタンスのフィールドの値のみを使用してエンコード可能である)
Motivation – JEP 390: Warnings for Value-Based Classes
https://openjdk.java.net/jeps/390
おそらく、JEP 390の中で最も期待されている文章は、Motivationの第2段落にあります(該当部分を強調しました)。
“The design and implementation of inline classes is sufficiently mature that we can confidently anticipate migrating certain classes in the Java Platform to become inline classes in a future release.”(inlineクラスの設計と実装は十分に成熟しており、自身を持ってJava Platformの特定のクラスを将来のリリースでinlineクラスに移行することを予想できる)
Motivation – JEP 390: Warnings for Value-Based Classes
https://openjdk.java.net/jeps/390
JEP 390のMotivationの章ではinlineクラス候補の特性を列挙しています。これらは前述の値ベース・クラスの特徴に非常に類似しています。
- final
- finalなインスタンスフィールドのみで宣言
- Objectを拡張、またはインスタンスフィールドを宣言せず、インスタンス初期化ロジックを持たない抽象クラスの階層
- privateなコンストラクタのみ宣言、もしくはそのコンストラクタが削除のために廃止されている
- ファクトリーメソッドの呼び出し(もしくはその他のインスタンス作成メカニズム)ごとに作成されるインスタンスが一意であることを約束しない
- メソッドを使ってオブジェクトIDに依存したり、公開したりしない
toString()
、equals()
、hashCode()
をオーバーライド- synchronizedメソッドを宣言せず、クライアントが同期実行することを推奨しない
JEP 390では、inlineクラスのプロパティが、値ベース・クラスのプロパティに近いことに対し驚くほどではないことについてもコメントしています。Java Platform APIでは値ベース・クラスという用語を使い、同様の制約を満たす特定のクラスを非公式に表現しています。クラスを値ベースとして表現している場合、inlineクラスになる可能性があります。
JEP 390 には、@ValueBased
アノテーションが、オブジェクトIDに依存しないと想定されるインスタンスのためのクラス、インターフェース、メソッド結果を示すために導入されるだろう、との説明があります。このアノテーションは、「==
やidentityHashCode
を使用する際に注意が必要であり、同期化を行うべきではないことを開発者に伝える」ことを目的としています。
Java’s System.identityHashCode
https://marxsoftware.blogspot.com/2010/11/javas-systemidentityhashcode.html
JEP 390のDescriptionの章は特に興味を引きました。その中では、@ValueBased
アノテーションが適用される可能性のあるJava Platform APIおよびJDK内の宣言をリストアップしています。ここには、以下のものが含まれています。
java.lang
のprimitive wrapper classes(プリミティブ・ラッパー・クラス、Boxed primitiveとも)java.lang.Runtime.Version
クラス- java.utilのoptionalクラス
Optional
、OptionalInt
、OptionalLong
、OptionalDouble
- java.timeの多くのクラスのAPI
Instant
、LocalDate
、LocalTime
、LocalDateTime
、ZonedDateTime
、ZoneId
、OffsetTime
、OffsetDateTime
、ZoneOffset
、Duration
、Period
、Year
,YearMonth
、MonthDay
, and,java.time.chrono
MinguoDate
、HijrahDate
、JapaneseDate
、ThaiBuddhistDate
java.lang.ProcessHandle
インターフェースとその実装クラスjava.util
のcollectionファクトリーの実装クラスList.of
、List.copyOf
、Set.of
、Set.copyOf
、Map.of
、Map.copyOf
、Map.ofEntries
、Map.entry
java.util.Optional
https://docs.oracle.com/javase/jp/15/docs/api/java.base/java/util/Optional.html
https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/Optional.html
java.time パッケージ
https://docs.oracle.com/javase/jp/15/docs/api/java.base/java/time/package-summary.html
https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/time/package-summary.html
@ValueBased
が付いたコンストラクタはjavacの警告で強調されるでしょう。
The javac Command
https://docs.oracle.com/en/java/javase/15/docs/specs/man/javac.html
JEP 390では、@ValueBased
のアノテーションが付いたクラスがinlineクラスになると、コンパイル時の警告や実行時の警告がどのようにしてエラーになるかについて議論しています。@ValueBased
クラスがinlineクラスになると、標準エラーが実行時警告にとってかわるでしょう。コンパイル時は、inlineクラス型の同期化によっても標準エラーを引き起こす可能性があります。コンパイラ警告はインターフェース型やメソッドの結果のために引き続き有用でしょう。
@ValueBased
アノテーションと関連する警告は、開発者が、inlineクラスと互換性のない方法で識別されたJDKの値ベース・クラスを使用するJavaコードを、より安全な代替手段に移行するのに役立つでしょう。JEP 390は、この詳細を説明しているだけでなく、inlineクラスに関するProject Valhallaの作業が成熟してきていることの証拠を提供しています。
Project Valhalla
https://openjdk.java.net/projects/valhalla/