has_class_mirror_holder(); }
- bool is_box() const { return access_flags().is_box_class(); }
- void set_is_box() { _access_flags.set_is_box_class(); }
+ bool is_value_based() { return _access_flags.is_value_based_class(); }
+ void set_is_value_based() { _access_flags.set_is_value_based_class(); }
bool is_cloneable() const;
void set_is_cloneable();
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
index 68e0ef34b2e..732923b51ac 100644
--- a/src/hotspot/share/runtime/arguments.cpp
+++ b/src/hotspot/share/runtime/arguments.cpp
@@ -4139,9 +4139,9 @@ jint Arguments::apply_ergo() {
}
#endif // COMPILER2
- if (FLAG_IS_CMDLINE(DiagnoseSyncOnPrimitiveWrappers)) {
- if (DiagnoseSyncOnPrimitiveWrappers == ObjectSynchronizer::LOG_WARNING && !log_is_enabled(Info, primitivewrappers)) {
- LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(primitivewrappers));
+ if (FLAG_IS_CMDLINE(DiagnoseSyncOnValueBasedClasses)) {
+ if (DiagnoseSyncOnValueBasedClasses == ObjectSynchronizer::LOG_WARNING && !log_is_enabled(Info, valuebasedclasses)) {
+ LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(valuebasedclasses));
}
}
return JNI_OK;
diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp
index 28147427680..7efabe34eeb 100644
--- a/src/hotspot/share/runtime/globals.hpp
+++ b/src/hotspot/share/runtime/globals.hpp
@@ -851,13 +851,13 @@ const intx ObjectAlignmentInBytes = 8;
range(500, max_intx) \
constraint(BiasedLockingDecayTimeFunc,AfterErgo) \
\
- product(intx, DiagnoseSyncOnPrimitiveWrappers, 0, DIAGNOSTIC, \
+ product(intx, DiagnoseSyncOnValueBasedClasses, 0, DIAGNOSTIC, \
"Detect and take action upon identifying synchronization on " \
- "primitive wrappers. Modes: " \
+ "value based classes. Modes: " \
"0: off; " \
"1: exit with fatal error; " \
"2: log message to stdout. Output file can be specified with " \
- " -Xlog:primitivewrappers. If JFR is running it will " \
+ " -Xlog:valuebasedclasses. If JFR is running it will " \
" also generate JFR events.") \
range(0, 2) \
\
diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp
index 17a7ba4f117..1fd6930d96c 100644
--- a/src/hotspot/share/runtime/synchronizer.cpp
+++ b/src/hotspot/share/runtime/synchronizer.cpp
@@ -333,7 +333,7 @@ bool ObjectSynchronizer::quick_enter(oop obj, Thread* self,
NoSafepointVerifier nsv;
if (obj == NULL) return false; // Need to throw NPE
- if (DiagnoseSyncOnPrimitiveWrappers != 0 && obj->klass()->is_box()) {
+ if (obj->klass()->is_value_based()) {
return false;
}
@@ -387,17 +387,23 @@ bool ObjectSynchronizer::quick_enter(oop obj, Thread* self,
return false; // revert to slow-path
}
-// Handle notifications when synchronizing on primitive wrappers
-void ObjectSynchronizer::handle_sync_on_primitive_wrapper(Handle obj, Thread* current) {
+// Handle notifications when synchronizing on value based classes
+void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, Thread* current) {
JavaThread* self = current->as_Java_thread();
frame last_frame = self->last_frame();
- if (last_frame.is_interpreted_frame()) {
+ bool bcp_was_adjusted = false;
+ // Don't decrement bcp if it points to the frame's first instruction. This happens when
+ // handle_sync_on_value_based_class() is called because of a synchronized method. There
+ // is no actual monitorenter instruction in the byte code in this case.
+ if (last_frame.is_interpreted_frame() &&
+ (last_frame.interpreter_frame_method()->code_base() < last_frame.interpreter_frame_bcp())) {
// adjust bcp to point back to monitorenter so that we print the correct line numbers
last_frame.interpreter_frame_set_bcp(last_frame.interpreter_frame_bcp() - 1);
+ bcp_was_adjusted = true;
}
- if (DiagnoseSyncOnPrimitiveWrappers == FATAL_EXIT) {
+ if (DiagnoseSyncOnValueBasedClasses == FATAL_EXIT) {
ResourceMark rm(self);
stringStream ss;
self->print_stack_on(&ss);
@@ -408,26 +414,26 @@ void ObjectSynchronizer::handle_sync_on_primitive_wrapper(Handle obj, Thread* cu
}
fatal("Synchronizing on object " INTPTR_FORMAT " of klass %s %s", p2i(obj()), obj->klass()->external_name(), base);
} else {
- assert(DiagnoseSyncOnPrimitiveWrappers == LOG_WARNING, "invalid value for DiagnoseSyncOnPrimitiveWrappers");
+ assert(DiagnoseSyncOnValueBasedClasses == LOG_WARNING, "invalid value for DiagnoseSyncOnValueBasedClasses");
ResourceMark rm(self);
- Log(primitivewrappers) pwlog;
+ Log(valuebasedclasses) vblog;
- pwlog.info("Synchronizing on object " INTPTR_FORMAT " of klass %s", p2i(obj()), obj->klass()->external_name());
+ vblog.info("Synchronizing on object " INTPTR_FORMAT " of klass %s", p2i(obj()), obj->klass()->external_name());
if (self->has_last_Java_frame()) {
- LogStream info_stream(pwlog.info());
+ LogStream info_stream(vblog.info());
self->print_stack_on(&info_stream);
} else {
- pwlog.info("Cannot find the last Java frame");
+ vblog.info("Cannot find the last Java frame");
}
- EventSyncOnPrimitiveWrapper event;
+ EventSyncOnValueBasedClass event;
if (event.should_commit()) {
- event.set_boxClass(obj->klass());
+ event.set_valueBasedClass(obj->klass());
event.commit();
}
}
- if (last_frame.is_interpreted_frame()) {
+ if (bcp_was_adjusted) {
last_frame.interpreter_frame_set_bcp(last_frame.interpreter_frame_bcp() + 1);
}
}
@@ -439,8 +445,8 @@ void ObjectSynchronizer::handle_sync_on_primitive_wrapper(Handle obj, Thread* cu
// changed. The implementation is extremely sensitive to race condition. Be careful.
void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, TRAPS) {
- if (DiagnoseSyncOnPrimitiveWrappers != 0 && obj->klass()->is_box()) {
- handle_sync_on_primitive_wrapper(obj, THREAD);
+ if (obj->klass()->is_value_based()) {
+ handle_sync_on_value_based_class(obj, THREAD);
}
if (UseBiasedLocking) {
@@ -586,8 +592,8 @@ void ObjectSynchronizer::reenter(Handle obj, intx recursions, TRAPS) {
// JNI locks on java objects
// NOTE: must use heavy weight monitor to handle jni monitor enter
void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) {
- if (DiagnoseSyncOnPrimitiveWrappers != 0 && obj->klass()->is_box()) {
- handle_sync_on_primitive_wrapper(obj, THREAD);
+ if (obj->klass()->is_value_based()) {
+ handle_sync_on_value_based_class(obj, THREAD);
}
// the current locking is from JNI instead of Java code
diff --git a/src/hotspot/share/runtime/synchronizer.hpp b/src/hotspot/share/runtime/synchronizer.hpp
index 16657c60e6f..35fe8def72a 100644
--- a/src/hotspot/share/runtime/synchronizer.hpp
+++ b/src/hotspot/share/runtime/synchronizer.hpp
@@ -161,7 +161,7 @@ class ObjectSynchronizer : AllStatic {
static size_t get_gvars_size();
static u_char* get_gvars_stw_random_addr();
- static void handle_sync_on_primitive_wrapper(Handle obj, Thread* current);
+ static void handle_sync_on_value_based_class(Handle obj, Thread* current);
};
// ObjectLocker enforces balanced locking and can never throw an
diff --git a/src/hotspot/share/utilities/accessFlags.hpp b/src/hotspot/share/utilities/accessFlags.hpp
index 9fe8f7acf3e..ab2f6a640af 100644
--- a/src/hotspot/share/utilities/accessFlags.hpp
+++ b/src/hotspot/share/utilities/accessFlags.hpp
@@ -67,7 +67,7 @@ enum {
JVM_ACC_HAS_FINAL_METHOD = 0x01000000, // True if klass has final method
JVM_ACC_IS_SHARED_CLASS = 0x02000000, // True if klass is shared
JVM_ACC_IS_HIDDEN_CLASS = 0x04000000, // True if klass is hidden
- JVM_ACC_IS_BOX_CLASS = 0x08000000, // True if klass is primitive wrapper
+ JVM_ACC_IS_VALUE_BASED_CLASS = 0x08000000, // True if klass is marked as a ValueBased class
// Klass* and Method* flags
JVM_ACC_HAS_LOCAL_VARIABLE_TABLE= 0x00200000,
@@ -152,7 +152,7 @@ class AccessFlags {
bool is_cloneable_fast () const { return (_flags & JVM_ACC_IS_CLONEABLE_FAST ) != 0; }
bool is_shared_class () const { return (_flags & JVM_ACC_IS_SHARED_CLASS ) != 0; }
bool is_hidden_class () const { return (_flags & JVM_ACC_IS_HIDDEN_CLASS ) != 0; }
- bool is_box_class () const { return (_flags & JVM_ACC_IS_BOX_CLASS ) != 0; }
+ bool is_value_based_class () const { return (_flags & JVM_ACC_IS_VALUE_BASED_CLASS ) != 0; }
// Klass* and Method* flags
bool has_localvariable_table () const { return (_flags & JVM_ACC_HAS_LOCAL_VARIABLE_TABLE) != 0; }
@@ -226,7 +226,7 @@ class AccessFlags {
void set_has_miranda_methods() { atomic_set_bits(JVM_ACC_HAS_MIRANDA_METHODS); }
void set_is_shared_class() { atomic_set_bits(JVM_ACC_IS_SHARED_CLASS); }
void set_is_hidden_class() { atomic_set_bits(JVM_ACC_IS_HIDDEN_CLASS); }
- void set_is_box_class() { atomic_set_bits(JVM_ACC_IS_BOX_CLASS); }
+ void set_is_value_based_class() { atomic_set_bits(JVM_ACC_IS_VALUE_BASED_CLASS); }
public:
// field flags
diff --git a/src/java.base/share/classes/java/lang/Boolean.java b/src/java.base/share/classes/java/lang/Boolean.java
index fc76dfe460f..0397277e68f 100644
--- a/src/java.base/share/classes/java/lang/Boolean.java
+++ b/src/java.base/share/classes/java/lang/Boolean.java
@@ -41,16 +41,23 @@ import static java.lang.constant.ConstantDescs.CD_Boolean;
* {@code boolean} in an object. An object of type
* {@code Boolean} contains a single field whose type is
* {@code boolean}.
- *
- * In addition, this class provides many methods for
+ *
+ *
In addition, this class provides many methods for
* converting a {@code boolean} to a {@code String} and a
* {@code String} to a {@code boolean}, as well as other
* constants and methods useful when dealing with a
* {@code boolean}.
*
+ *
This is a value-based
+ * class; programmers should treat instances that are
+ * {@linkplain #equals(Object) equal} as interchangeable and should not
+ * use instances for synchronization, or unpredictable behavior may
+ * occur. For example, in a future release, synchronization may fail.
+ *
* @author Arthur van Hoff
* @since 1.0
*/
+@jdk.internal.ValueBased
public final class Boolean implements java.io.Serializable,
Comparable, Constable
{
@@ -98,7 +105,7 @@ public final class Boolean implements java.io.Serializable,
* Also consider using the final fields {@link #TRUE} and {@link #FALSE}
* if possible.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Boolean(boolean value) {
this.value = value;
}
@@ -118,7 +125,7 @@ public final class Boolean implements java.io.Serializable,
* {@code boolean} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Boolean} object.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Boolean(String s) {
this(parseBoolean(s));
}
diff --git a/src/java.base/share/classes/java/lang/Byte.java b/src/java.base/share/classes/java/lang/Byte.java
index 9b004bfae6d..c80a6fc9fe0 100644
--- a/src/java.base/share/classes/java/lang/Byte.java
+++ b/src/java.base/share/classes/java/lang/Byte.java
@@ -48,11 +48,18 @@ import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
* byte}, as well as other constants and methods useful when dealing
* with a {@code byte}.
*
+ * This is a value-based
+ * class; programmers should treat instances that are
+ * {@linkplain #equals(Object) equal} as interchangeable and should not
+ * use instances for synchronization, or unpredictable behavior may
+ * occur. For example, in a future release, synchronization may fail.
+ *
* @author Nakul Saraiya
* @author Joseph D. Darcy
* @see java.lang.Number
* @since 1.1
*/
+@jdk.internal.ValueBased
public final class Byte extends Number implements Comparable, Constable {
/**
@@ -337,7 +344,7 @@ public final class Byte extends Number implements Comparable, Constable {
* {@link #valueOf(byte)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Byte(byte value) {
this.value = value;
}
@@ -360,7 +367,7 @@ public final class Byte extends Number implements Comparable, Constable {
* {@code byte} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Byte} object.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Byte(String s) throws NumberFormatException {
this.value = parseByte(s, 10);
}
diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java
index 96238563354..fb2431d045b 100644
--- a/src/java.base/share/classes/java/lang/Character.java
+++ b/src/java.base/share/classes/java/lang/Character.java
@@ -122,6 +122,12 @@ import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
* encoding. For more information on Unicode terminology, refer to the
* Unicode Glossary.
*
+ * This is a value-based
+ * class; programmers should treat instances that are
+ * {@linkplain #equals(Object) equal} as interchangeable and should not
+ * use instances for synchronization, or unpredictable behavior may
+ * occur. For example, in a future release, synchronization may fail.
+ *
* @author Lee Boynton
* @author Guy Steele
* @author Akira Tanaka
@@ -129,6 +135,7 @@ import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
* @author Ulf Zibis
* @since 1.0
*/
+@jdk.internal.ValueBased
public final
class Character implements java.io.Serializable, Comparable, Constable {
/**
@@ -8501,7 +8508,7 @@ class Character implements java.io.Serializable, Comparable, Constabl
* {@link #valueOf(char)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Character(char value) {
this.value = value;
}
diff --git a/src/java.base/share/classes/java/lang/Double.java b/src/java.base/share/classes/java/lang/Double.java
index 729adcf5b03..36e9086e1c4 100644
--- a/src/java.base/share/classes/java/lang/Double.java
+++ b/src/java.base/share/classes/java/lang/Double.java
@@ -46,11 +46,18 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
* constants and methods useful when dealing with a
* {@code double}.
*
+ * This is a value-based
+ * class; programmers should treat instances that are
+ * {@linkplain #equals(Object) equal} as interchangeable and should not
+ * use instances for synchronization, or unpredictable behavior may
+ * occur. For example, in a future release, synchronization may fail.
+ *
* @author Lee Boynton
* @author Arthur van Hoff
* @author Joseph D. Darcy
* @since 1.0
*/
+@jdk.internal.ValueBased
public final class Double extends Number
implements Comparable, Constable, ConstantDesc {
/**
@@ -605,7 +612,7 @@ public final class Double extends Number
* {@link #valueOf(double)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Double(double value) {
this.value = value;
}
@@ -626,7 +633,7 @@ public final class Double extends Number
* {@code double} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Double} object.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Double(String s) throws NumberFormatException {
value = parseDouble(s);
}
diff --git a/src/java.base/share/classes/java/lang/Float.java b/src/java.base/share/classes/java/lang/Float.java
index 0cebe7848ac..478b5a27a7b 100644
--- a/src/java.base/share/classes/java/lang/Float.java
+++ b/src/java.base/share/classes/java/lang/Float.java
@@ -45,11 +45,18 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
* constants and methods useful when dealing with a
* {@code float}.
*
+ * This is a value-based
+ * class; programmers should treat instances that are
+ * {@linkplain #equals(Object) equal} as interchangeable and should not
+ * use instances for synchronization, or unpredictable behavior may
+ * occur. For example, in a future release, synchronization may fail.
+ *
* @author Lee Boynton
* @author Arthur van Hoff
* @author Joseph D. Darcy
* @since 1.0
*/
+@jdk.internal.ValueBased
public final class Float extends Number
implements Comparable, Constable, ConstantDesc {
/**
@@ -518,7 +525,7 @@ public final class Float extends Number
* {@link #valueOf(float)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Float(float value) {
this.value = value;
}
@@ -534,7 +541,7 @@ public final class Float extends Number
* static factory method {@link #valueOf(float)} method as follows:
* {@code Float.valueOf((float)value)}.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Float(double value) {
this.value = (float)value;
}
@@ -555,7 +562,7 @@ public final class Float extends Number
* {@code float} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Float} object.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Float(String s) throws NumberFormatException {
value = parseFloat(s);
}
diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java
index f75be73b307..815ae10e540 100644
--- a/src/java.base/share/classes/java/lang/Integer.java
+++ b/src/java.base/share/classes/java/lang/Integer.java
@@ -50,6 +50,12 @@ import static java.lang.String.UTF16;
* {@code int}, as well as other constants and methods useful when
* dealing with an {@code int}.
*
+ * This is a value-based
+ * class; programmers should treat instances that are
+ * {@linkplain #equals(Object) equal} as interchangeable and should not
+ * use instances for synchronization, or unpredictable behavior may
+ * occur. For example, in a future release, synchronization may fail.
+ *
*
Implementation note: The implementations of the "bit twiddling"
* methods (such as {@link #highestOneBit(int) highestOneBit} and
* {@link #numberOfTrailingZeros(int) numberOfTrailingZeros}) are
@@ -62,6 +68,7 @@ import static java.lang.String.UTF16;
* @author Joseph D. Darcy
* @since 1.0
*/
+@jdk.internal.ValueBased
public final class Integer extends Number
implements Comparable, Constable, ConstantDesc {
/**
@@ -1085,7 +1092,7 @@ public final class Integer extends Number
* {@link #valueOf(int)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Integer(int value) {
this.value = value;
}
@@ -1107,7 +1114,7 @@ public final class Integer extends Number
* {@code int} primitive, or use {@link #valueOf(String)}
* to convert a string to an {@code Integer} object.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
diff --git a/src/java.base/share/classes/java/lang/Long.java b/src/java.base/share/classes/java/lang/Long.java
index 15c9ee1cc31..21323e19de6 100644
--- a/src/java.base/share/classes/java/lang/Long.java
+++ b/src/java.base/share/classes/java/lang/Long.java
@@ -50,6 +50,12 @@ import static java.lang.String.UTF16;
* long}, as well as other constants and methods useful when dealing
* with a {@code long}.
*
+ * This is a value-based
+ * class; programmers should treat instances that are
+ * {@linkplain #equals(Object) equal} as interchangeable and should not
+ * use instances for synchronization, or unpredictable behavior may
+ * occur. For example, in a future release, synchronization may fail.
+ *
*
Implementation note: The implementations of the "bit twiddling"
* methods (such as {@link #highestOneBit(long) highestOneBit} and
* {@link #numberOfTrailingZeros(long) numberOfTrailingZeros}) are
@@ -62,6 +68,7 @@ import static java.lang.String.UTF16;
* @author Joseph D. Darcy
* @since 1.0
*/
+@jdk.internal.ValueBased
public final class Long extends Number
implements Comparable, Constable, ConstantDesc {
/**
@@ -1316,7 +1323,7 @@ public final class Long extends Number
* {@link #valueOf(long)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Long(long value) {
this.value = value;
}
@@ -1339,7 +1346,7 @@ public final class Long extends Number
* {@code long} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Long} object.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Long(String s) throws NumberFormatException {
this.value = parseLong(s, 10);
}
diff --git a/src/java.base/share/classes/java/lang/ProcessHandle.java b/src/java.base/share/classes/java/lang/ProcessHandle.java
index 32b34d13414..229f98d0b6f 100644
--- a/src/java.base/share/classes/java/lang/ProcessHandle.java
+++ b/src/java.base/share/classes/java/lang/ProcessHandle.java
@@ -81,16 +81,17 @@ import java.util.stream.Stream;
*
* The {@code ProcessHandle} static factory methods return instances that are
* value-based,
- * immutable and thread-safe.
- * Use of identity-sensitive operations (including reference equality
- * ({@code ==}), identity hash code, or synchronization) on these instances of
- * {@code ProcessHandle} may have unpredictable results and should be avoided.
- * Use {@link #equals(Object) equals} or
- * {@link #compareTo(ProcessHandle) compareTo} methods to compare ProcessHandles.
+ * immutable and thread-safe. Programmers should treat instances that are
+ * {@linkplain #equals(Object) equal} as interchangeable and should not
+ * use instances for synchronization, or unpredictable behavior may occur.
+ * For example, in a future release, synchronization may fail.
+ * Use the {@code equals} or {@link #compareTo(ProcessHandle) compareTo} methods
+ * to compare ProcessHandles.
*
* @see Process
* @since 9
*/
+@jdk.internal.ValueBased
public interface ProcessHandle extends Comparable {
/**
diff --git a/src/java.base/share/classes/java/lang/ProcessHandleImpl.java b/src/java.base/share/classes/java/lang/ProcessHandleImpl.java
index f51720d99f5..92634d9b120 100644
--- a/src/java.base/share/classes/java/lang/ProcessHandleImpl.java
+++ b/src/java.base/share/classes/java/lang/ProcessHandleImpl.java
@@ -48,6 +48,7 @@ import static java.security.AccessController.doPrivileged;
* @see Process
* @since 9
*/
+@jdk.internal.ValueBased
final class ProcessHandleImpl implements ProcessHandle {
/**
* Default size of stack for reaper processes.
diff --git a/src/java.base/share/classes/java/lang/Runtime.java b/src/java.base/share/classes/java/lang/Runtime.java
index dae8be95ce6..2519eb88ca6 100644
--- a/src/java.base/share/classes/java/lang/Runtime.java
+++ b/src/java.base/share/classes/java/lang/Runtime.java
@@ -941,14 +941,15 @@ public class Runtime {
* $VNUM(-$PRE)?
*
*
- * This is a value-based
- * class; use of identity-sensitive operations (including reference equality
- * ({@code ==}), identity hash code, or synchronization) on instances of
- * {@code Version} may have unpredictable results and should be avoided.
- *
+ * This is a value-based
+ * class; programmers should treat instances that are
+ * {@linkplain #equals(Object) equal} as interchangeable and should not
+ * use instances for synchronization, or unpredictable behavior may
+ * occur. For example, in a future release, synchronization may fail.
*
* @since 9
*/
+ @jdk.internal.ValueBased
public static final class Version
implements Comparable
{
diff --git a/src/java.base/share/classes/java/lang/Short.java b/src/java.base/share/classes/java/lang/Short.java
index 4f293496579..00d4a91d37b 100644
--- a/src/java.base/share/classes/java/lang/Short.java
+++ b/src/java.base/share/classes/java/lang/Short.java
@@ -47,11 +47,18 @@ import static java.lang.constant.ConstantDescs.DEFAULT_NAME;
* {@code short}, as well as other constants and methods useful when
* dealing with a {@code short}.
*
+ * This is a value-based
+ * class; programmers should treat instances that are
+ * {@linkplain #equals(Object) equal} as interchangeable and should not
+ * use instances for synchronization, or unpredictable behavior may
+ * occur. For example, in a future release, synchronization may fail.
+ *
* @author Nakul Saraiya
* @author Joseph D. Darcy
* @see java.lang.Number
* @since 1.1
*/
+@jdk.internal.ValueBased
public final class Short extends Number implements Comparable, Constable {
/**
@@ -342,7 +349,7 @@ public final class Short extends Number implements Comparable, Constable
* {@link #valueOf(short)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Short(short value) {
this.value = value;
}
@@ -365,7 +372,7 @@ public final class Short extends Number implements Comparable, Constable
* {@code short} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Short} object.
*/
- @Deprecated(since="9")
+ @Deprecated(since="9", forRemoval = true)
public Short(String s) throws NumberFormatException {
this.value = parseShort(s, 10);
}
diff --git a/src/java.base/share/classes/java/lang/constant/ConstantDesc.java b/src/java.base/share/classes/java/lang/constant/ConstantDesc.java
index 5ffb5b2aded..9d410e6774b 100644
--- a/src/java.base/share/classes/java/lang/constant/ConstantDesc.java
+++ b/src/java.base/share/classes/java/lang/constant/ConstantDesc.java
@@ -57,8 +57,8 @@ import java.lang.invoke.VarHandle.VarHandleDesc;
* Constants describing various common constants (such as {@link ClassDesc}
* instances for platform types) can be found in {@link ConstantDescs}.
*
- *
Implementations of {@linkplain ConstantDesc} must be
- * value-based classes.
+ *
Implementations of {@linkplain ConstantDesc} should be immutable
+ * and their behavior should not rely on object identity.
*
*
Non-platform classes should not implement {@linkplain ConstantDesc} directly.
* Instead, they should extend {@link DynamicConstantDesc} (as {@link EnumDesc}
diff --git a/src/java.base/share/classes/java/lang/constant/DynamicCallSiteDesc.java b/src/java.base/share/classes/java/lang/constant/DynamicCallSiteDesc.java
index f336bc5fb4e..b57f73c0fb9 100644
--- a/src/java.base/share/classes/java/lang/constant/DynamicCallSiteDesc.java
+++ b/src/java.base/share/classes/java/lang/constant/DynamicCallSiteDesc.java
@@ -41,8 +41,8 @@ import static java.util.stream.Collectors.joining;
* A nominal descriptor for an
* {@code invokedynamic} call site.
*
- *
Concrete subtypes of {@linkplain DynamicCallSiteDesc} must be
- * value-based.
+ *
Concrete subtypes of {@linkplain DynamicCallSiteDesc} should be immutable
+ * and their behavior should not rely on object identity.
*
* @since 12
*/
diff --git a/src/java.base/share/classes/java/lang/constant/DynamicConstantDesc.java b/src/java.base/share/classes/java/lang/constant/DynamicConstantDesc.java
index 2ff7a0ebf89..4efd3dde3c3 100644
--- a/src/java.base/share/classes/java/lang/constant/DynamicConstantDesc.java
+++ b/src/java.base/share/classes/java/lang/constant/DynamicConstantDesc.java
@@ -49,8 +49,8 @@ import static java.util.stream.Collectors.joining;
* dynamic constant (one described in the constant pool with
* {@code Constant_Dynamic_info}.)
*
- *
Concrete subtypes of {@linkplain DynamicConstantDesc} must be
- * value-based.
+ *
Concrete subtypes of {@linkplain DynamicConstantDesc} should be immutable
+ * and their behavior should not rely on object identity.
*
* @param the type of the dynamic constant
*
diff --git a/src/java.base/share/classes/java/lang/doc-files/ValueBased.html b/src/java.base/share/classes/java/lang/doc-files/ValueBased.html
index fe720a37be7..86d9b359557 100644
--- a/src/java.base/share/classes/java/lang/doc-files/ValueBased.html
+++ b/src/java.base/share/classes/java/lang/doc-files/ValueBased.html
@@ -31,36 +31,43 @@
{@index "Value-based Classes"}
-Some classes, such as java.util.Optional
and
-java.time.LocalDateTime
, are value-based. Instances of a
-value-based class:
+Some classes, such as java.lang.Integer
and
+java.time.LocalDate
, are value-based.
+A value-based class has the following properties:
- - are final and immutable (though may contain references to mutable
- objects);
- - have implementations of
equals
,
- hashCode
, and toString
which are computed
- solely from the instance's state and not from its identity or the state
- of any other object or variable;
- - make no use of identity-sensitive operations such as reference
- equality (
==
) between instances, identity hash code of
- instances, or synchronization on an instances's intrinsic lock;
- - are considered equal solely based on
equals()
, not
- based on reference equality (==
);
- - do not have accessible constructors, but are instead instantiated
- through factory methods which make no commitment as to the identity
- of returned instances;
- - are freely substitutable when equal, meaning that interchanging
- any two instances
x
and y
that are equal
- according to equals()
in any computation or method
- invocation should produce no visible change in behavior.
-
+ - the class declares only final instance fields (though these may contain references
+ to mutable objects);
+ - the class's implementations of
equals
, hashCode
,
+ and toString
compute their results solely from the values
+ of the class's instance fields (and the members of the objects they
+ reference), not from the instance's identity;
+ - the class's methods treat instances as freely substitutable
+ when equal, meaning that interchanging any two instances
x
and
+ y
that are equal according to equals()
produces no
+ visible change in the behavior of the class's methods;
+ - the class performs no synchronization using an instance's monitor;
+ - the class does not declare (or has deprecated any) accessible constructors;
+ - the class does not provide any instance creation mechanism that promises
+ a unique identity on each method call—in particular, any factory
+ method's contract must allow for the possibility that if two independently-produced
+ instances are equal according to
equals()
, they may also be
+ equal according to ==
;
+ - the class is final, and extends either
Object
or a hierarchy of
+ abstract classes that declare no instance fields or instance initializers
+ and whose constructors are empty.
-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
+
When two instances of a value-based class are equal (according to `equals`), a program
+ should not attempt to distinguish between their identities, 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.
+ serialization, or any other identity-sensitive mechanism.
+
+Synchronization on instances of value-based classes is strongly discouraged,
+ because the programmer cannot guarantee exclusive ownership of the
+ associated monitor.
+
+Identity-related behavior of value-based classes may change in a future release.
+ For example, synchronization may fail.
+