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.