mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8225054: Compiler implementation for records
8225052: javax.lang.model support for records 8225053: Preview APIs support for records 8225055: Javadoc for records 8226314: com.sun.source support for records 8227113: Specification for java.lang.Record 8233526: JVM support for records Implement records in the compiler and the JVM, including serialization, reflection and APIs support Co-authored-by: Brian Goetz <brian.goetz@oracle.com> Co-authored-by: Maurizio Cimadamore <maurizio.cimadamore@oracle.com> Co-authored-by: Harold Seigel <harold.seigel@oracle.com> Co-authored-by: Joe Darcy <joe.darcy@oracle.com> Co-authored-by: Jonathan Gibbons <jonathan.gibbons@oracle.com> Co-authored-by: Chris Hegarty <chris.hegarty@oracle.com> Co-authored-by: Jan Lahoda <jan.lahoda@oracle.com> Reviewed-by: mcimadamore, briangoetz, alanb, darcy, chegar, jrose, jlahoda, coleenp, dholmes, lfoltan, mchung, sadayapalam, hannesw, sspitsyn
This commit is contained in:
parent
0a375cfa2d
commit
827e5e3226
351 changed files with 24958 additions and 6395 deletions
|
@ -26,7 +26,9 @@
|
|||
package java.io;
|
||||
|
||||
import java.io.ObjectStreamClass.WeakClassKey;
|
||||
import java.io.ObjectStreamClass.RecordSupport;
|
||||
import java.lang.System.Logger;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
@ -218,6 +220,39 @@ import sun.reflect.misc.ReflectUtil;
|
|||
* Similarly, any serialPersistentFields or serialVersionUID field declarations
|
||||
* are also ignored--all enum types have a fixed serialVersionUID of 0L.
|
||||
*
|
||||
* @implSpec
|
||||
* <a id="record-serialization"></a>
|
||||
* Records are serialized differently than ordinary serializable or externalizable
|
||||
* objects. The serialized form of a record object is a sequence of values derived
|
||||
* from the record components. The stream format of a record object is the same as
|
||||
* that of an ordinary object in the stream. During deserialization, if the local
|
||||
* class equivalent of the specified stream class descriptor is a record class,
|
||||
* then first the stream fields are read and reconstructed to serve as the record's
|
||||
* component values; and second, a record object is created by invoking the
|
||||
* record's <i>canonical</i> constructor with the component values as arguments (or the
|
||||
* default value for component's type if a component value is absent from the
|
||||
* stream).
|
||||
* Like other serializable or externalizable objects, record objects can function
|
||||
* as the target of back references appearing subsequently in the serialization
|
||||
* stream. However, a cycle in the graph where the record object is referred to,
|
||||
* either directly or transitively, by one of its components, is not preserved.
|
||||
* The record components are deserialized prior to the invocation of the record
|
||||
* constructor, hence this limitation (see
|
||||
* <a href="{@docRoot}/../specs/serialization/serial-arch.html#cyclic-references">
|
||||
* [Section 1.14, "Circular References"</a> for additional information).
|
||||
* The process by which record objects are serialized or externalized cannot be
|
||||
* customized; any class-specific writeObject, readObject, readObjectNoData,
|
||||
* writeExternal, and readExternal methods defined by record classes are
|
||||
* ignored during serialization and deserialization. However, a substitute object
|
||||
* to be serialized or a designate replacement may be specified, by the
|
||||
* writeReplace and readResolve methods, respectively. Any
|
||||
* serialPersistentFields field declaration is ignored. Documenting serializable
|
||||
* fields and data for record classes is unnecessary, since there is no variation
|
||||
* in the serial form, other than whether a substitute or replacement object is
|
||||
* used. The serialVersionUID of a record class is 0L unless explicitly
|
||||
* declared. The requirement for matching serialVersionUID values is waived for
|
||||
* record classes.
|
||||
*
|
||||
* @author Mike Warres
|
||||
* @author Roger Riggs
|
||||
* @see java.io.DataInput
|
||||
|
@ -2047,6 +2082,11 @@ public class ObjectInputStream
|
|||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("preview")
|
||||
private static boolean isRecord(Class<?> cls) {
|
||||
return cls.isRecord();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and returns "ordinary" (i.e., not a String, Class,
|
||||
* ObjectStreamClass, array, or enum constant) object, or null if object's
|
||||
|
@ -2085,7 +2125,12 @@ public class ObjectInputStream
|
|||
handles.markException(passHandle, resolveEx);
|
||||
}
|
||||
|
||||
if (desc.isExternalizable()) {
|
||||
final boolean isRecord = cl != null && isRecord(cl) ? true : false;
|
||||
if (isRecord) {
|
||||
assert obj == null;
|
||||
obj = readRecord(desc);
|
||||
handles.setObject(passHandle, obj);
|
||||
} else if (desc.isExternalizable()) {
|
||||
readExternalData((Externalizable) obj, desc);
|
||||
} else {
|
||||
readSerialData(obj, desc);
|
||||
|
@ -2171,6 +2216,43 @@ public class ObjectInputStream
|
|||
*/
|
||||
}
|
||||
|
||||
/** Reads a record. */
|
||||
private Object readRecord(ObjectStreamClass desc) throws IOException {
|
||||
ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
|
||||
if (slots.length != 1) {
|
||||
// skip any superclass stream field values
|
||||
for (int i = 0; i < slots.length-1; i++) {
|
||||
ObjectStreamClass slotDesc = slots[i].desc;
|
||||
if (slots[i].hasData) {
|
||||
defaultReadFields(null, slotDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FieldValues fieldValues = defaultReadFields(null, desc);
|
||||
|
||||
// retrieve the canonical constructor
|
||||
MethodHandle ctrMH = desc.getRecordConstructor();
|
||||
|
||||
// bind the stream field values
|
||||
ctrMH = RecordSupport.bindCtrValues(ctrMH, desc, fieldValues);
|
||||
|
||||
try {
|
||||
return ctrMH.invoke();
|
||||
} catch (Exception e) {
|
||||
InvalidObjectException ioe = new InvalidObjectException(e.getMessage());
|
||||
ioe.initCause(e);
|
||||
throw ioe;
|
||||
} catch (Error e) {
|
||||
throw e;
|
||||
} catch (Throwable t) {
|
||||
ObjectStreamException ose = new InvalidObjectException(
|
||||
"ReflectiveOperationException during deserialization");
|
||||
ose.initCause(t);
|
||||
throw ose;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads (or attempts to skip, if obj is null or is tagged with a
|
||||
* ClassNotFoundException) instance data for each serializable class of
|
||||
|
@ -2317,7 +2399,7 @@ public class ObjectInputStream
|
|||
}
|
||||
}
|
||||
|
||||
private class FieldValues {
|
||||
/*package-private*/ class FieldValues {
|
||||
final byte[] primValues;
|
||||
final Object[] objValues;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue