-
JEP
-
Resolution: Unresolved
-
P4
-
None
-
None
-
Feature
-
Open
-
SE
-
-
XS
-
XS
Summary
Identify libraries in the Java Platform that rely on object identity. Provide
javac
warnings about improper usages of these libraries, when inputs are
instances of certain value-based Java Platform classes.
Motivation
Some Java Platform classes have been designated
value-based classes
in the API specifications.
These classes discourage developers from relying on the unique identities of
instances—if two instances are equals
, whether or not they are ==
should
be irrelevant. Instances are always created via factory methods, which
deliberately avoid making commitments about whether results will be ==
to
previously-returned results.
In the future, we anticipate that these classes will evolve into value classes whose instances, under an enhanced Java programming model, simply do not have unique identities. Certain key Java Platform libraries are expected to throw an exception when asked to operate on an instance of a value class.
Many value-based classes are widely used, and, despite the disclaimers in their documentation, may occasionally have instances be used as inputs to these identity-sensitive standard libraries. In anticipation of the future behavioral change, developers would benefit from diagnostics that identify misuse of value-based classes and encourage refactoring beforehand.
This JEP can build on the work of Warnings for Value-Based Classes,
which warned about synchronized
statements being applied to the same set
of class instances.
Description
Value-based classes
The following classes are value-based, and have been marked (since JEP 390)
with the @jdk.internal.ValueBased
annotation:
The primitive wrapper classes in
java.lang
;The class
java.lang.Runtime.Version
;The "optional" classes in
java.util
:Optional
,OptionalInt
,OptionalLong
, andOptionalDouble
;Many classes in the
java.time
API:Instant
,LocalDate
,LocalTime
,LocalDateTime
,ZonedDateTime
,ZoneId
,OffsetTime
,OffsetDateTime
,ZoneOffset
,Duration
,Period
,Year
,YearMonth
, andMonthDay
, and, injava.time.chrono
:MinguoDate
,HijrahDate
,JapaneseDate
, andThaiBuddhistDate
;The implementation classes of the interface
java.lang.ProcessHandle
;The implementation classes of the collection factories in
java.util
:List.of
,List.copyOf
,Set.of
,Set.copyOf
,Map.of
,Map.copyOf
,Map.ofEntries
, andMap.entry
.
The design of value classes has evolved in some ways since JEP 390. To better align with future plans, the following changes should be made:
It is no longer anticipated that an abstract class or interface will be able to require all subclasses to be value classes. Thus, the interface
java.lang.ProcessHandle
should no longer be marked@ValueBased
.Constructor invocations are expected to be binary compatible across a value class migration. While value-based classes will still discourage use of their constructors, it is no longer necessary to deprecate for removal the constructors of the primitive wrapper classes. Those constructors can be rolled back to simply being designated
@Deprecated
.
Identity-sensitive operations
A new JDK-internal annotation interface, @jdk.internal.RequiresIdentity
, is
declared with target types PARAMETER
and TYPE_PARAMETER
. The
@RequiresIdentity
annotation expresses the expectation that an argument to
a given method or constructor parameter will be an object with a unique
identity, not an instance of a value-based class; or that the type argument
to a given type parameter will not be a value-based class type.
An appropriate application of the @RequiresIdentity
annotation is the set of
APIs related to object lifespan and garbage collection. Because instances of
value-based classes have unpredictable identity, they should not be used with
these garbage-collection APIs.
The following parameters and type parameters in standard libraries related to
garbage collection are marked with @RequiresIdentity
:
- The
referent
parameter of all constructors in classesPhantomReference
,SoftReference
, andWeakReference
- The
obj
parameter ofCleaner.register
- The type parameter
T
ofReference
,PhantomReference
,SoftReference
,WeakReference
, andReferenceQueue
- The
key
parameter ofWeakHashMap.put
- The type parameter
K
ofWeakHashMap
Work on this JEP may identify a few other candidate identity-sensitive APIs that
should be marked with @RequiresIdentity
.
Compile-time warnings
The javac
warning category synchronization
is intended to diagnose misuse
of value-based classes, but has an overly-specific name. It should be renamed
identity
, perhaps with alias support for the old name.
Whenever javac
encounters an expression of a value-based class type being
passed to a parameter marked @RequiresIdentity
, or a value-based class type
argument instantiating a type parameter marked RequiresIdentity
, it produces
an identity
warning.
Developers can request to print these warnings with -Xlint:identity
, and
suppress them in the source code with @SuppressWarnings("identity")
.
Scope of changes
Java SE: This JEP modifies Java SE by rolling back the "for removal" deprecation of the primitive wrapper class constructors.
JDK: The diagnostics produced by javac
are quality-of-implementation
features, and are not part of the Java Language Specifications.
Implementation: New annotations and methods are JDK-internal, not part of any publicly-accessible API.
Alternatives
The Value Classes and Objects JEP will migrate many value-based classes to be value classes. At that point, when preview features are enabled, attempts to use these classes' instances with identity-sensitive APIs will trigger run-time failures. This may be a "good enough" migration experience. But this JEP hopes to smooth the migration curve by warning about conflicts in an earlier release, catching problems at compile time rather than run time, and producing warnings even when preview features are disabled.
We considered supplementary warnings at run time, but existing run-time
diagnostics tend to support only JVM features, not library features. It's also
not clear there would be much incremental benefit to run-time warnings beyond
what will already be caught by javac
.
We have considered strategies for generalizing the garbage collection APIs to work with identityless objects, but it is hard to define intuitive, reasonable behavior for these operations.
Behavioral changes are always going to be difficult for some users, and we could decide to prioritize compatibility over evolution. We believe, however, that the future benefits of value classes will far outweigh the costs of migration.
It is possible that third parties will want to express their own value-based
classes or identity-sensitive operations, and get the same javac
warnings.
This could be achieved by making the relevant annotations part of a public API.
But we've decided we need more evidence of third-party use cases before defining
such an API.
Dependencies
Warnings for Value-Based Classes, delivered in Java 16,
introduced the @ValueBased
annotation on JDK classes and introduced the
javac
warnings about misuse of synchronization. This JEP builds on this
earlier work.
Value Classes and Objects (Preview) will implement the behavioral
changes that this JEP warns about. It may be an opportunity to standardize the
@RequiresIdentity
anotation for use with libraries outside the JDK. javac
can be expected to produce warnings whenever a concrete value class type is used
with a @RequiresIdentity
parameter or type parameter.