src/java.base/share/classes/java/io/ObjectStreamClass.java
Print this page
*** 1260,1269 ****
--- 1260,1277 ----
void setObjFieldValues(Object obj, Object[] vals) {
fieldRefl.setObjFieldValues(obj, vals);
}
/**
+ * Returns true if the field reflector has one, or more, underlying final
+ * fields.
+ */
+ boolean hasFinalField() {
+ return fieldRefl.hasFinal();
+ }
+
+ /**
* Calculates and sets serializable field offsets, as well as primitive
* data size and object field count totals. Throws InvalidClassException
* if fields are illegally ordered.
*/
private void computeFieldOffsets() throws InvalidClassException {
*** 1884,1893 ****
--- 1892,1903 ----
private final int[] offsets;
/** field type codes */
private final char[] typeCodes;
/** field types */
private final Class<?>[] types;
+ /** true if at least one underlying field is final */
+ private final boolean hasFinal;
/**
* Constructs FieldReflector capable of setting/getting values from the
* subset of fields whose ObjectStreamFields contain non-null
* reflective Field objects. ObjectStreamFields with null Fields are
*** 1902,1931 ****
offsets = new int[nfields];
typeCodes = new char[nfields];
ArrayList<Class<?>> typeList = new ArrayList<>();
Set<Long> usedKeys = new HashSet<>();
!
for (int i = 0; i < nfields; i++) {
ObjectStreamField f = fields[i];
Field rf = f.getField();
! long key = (rf != null) ?
! unsafe.objectFieldOffset(rf) : Unsafe.INVALID_FIELD_OFFSET;
readKeys[i] = key;
writeKeys[i] = usedKeys.add(key) ?
key : Unsafe.INVALID_FIELD_OFFSET;
offsets[i] = f.getOffset();
typeCodes[i] = f.getTypeCode();
if (!f.isPrimitive()) {
typeList.add((rf != null) ? rf.getType() : null);
}
}
types = typeList.toArray(new Class<?>[typeList.size()]);
numPrimFields = nfields - types.length;
}
/**
* Returns list of ObjectStreamFields representing fields operated on
* by this reflector. The shared/unshared values and Field objects
* contained by ObjectStreamFields in the list reflect their bindings
* to locally defined serializable fields.
--- 1912,1957 ----
offsets = new int[nfields];
typeCodes = new char[nfields];
ArrayList<Class<?>> typeList = new ArrayList<>();
Set<Long> usedKeys = new HashSet<>();
! boolean hf = false;
for (int i = 0; i < nfields; i++) {
ObjectStreamField f = fields[i];
Field rf = f.getField();
! long key;
! if (rf != null) {
! key = unsafe.objectFieldOffset(rf);
! if (!hf && isFinal(rf)) {
! hf = true;
! }
! } else {
! key = Unsafe.INVALID_FIELD_OFFSET;
! }
readKeys[i] = key;
writeKeys[i] = usedKeys.add(key) ?
key : Unsafe.INVALID_FIELD_OFFSET;
offsets[i] = f.getOffset();
typeCodes[i] = f.getTypeCode();
if (!f.isPrimitive()) {
typeList.add((rf != null) ? rf.getType() : null);
}
}
+ hasFinal = hf;
types = typeList.toArray(new Class<?>[typeList.size()]);
numPrimFields = nfields - types.length;
}
+ private static boolean isFinal(Field field) {
+ return (field.getModifiers() & Modifier.FINAL) != 0;
+ }
+
+ public boolean hasFinal() {
+ return hasFinal;
+ }
+
/**
* Returns list of ObjectStreamFields representing fields operated on
* by this reflector. The shared/unshared values and Field objects
* contained by ObjectStreamFields in the list reflect their bindings
* to locally defined serializable fields.