diff options
Diffstat (limited to 'luni/src/main')
-rw-r--r-- | luni/src/main/java/java/io/ObjectInputStream.java | 11 | ||||
-rw-r--r-- | luni/src/main/java/java/io/ObjectOutputStream.java | 8 | ||||
-rw-r--r-- | luni/src/main/java/java/io/ObjectStreamClass.java | 36 |
3 files changed, 37 insertions, 18 deletions
diff --git a/luni/src/main/java/java/io/ObjectInputStream.java b/luni/src/main/java/java/io/ObjectInputStream.java index f26549d..17a6974 100644 --- a/luni/src/main/java/java/io/ObjectInputStream.java +++ b/luni/src/main/java/java/io/ObjectInputStream.java @@ -23,7 +23,6 @@ import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Arrays; @@ -1064,12 +1063,10 @@ public class ObjectInputStream extends InputStream implements ObjectInput, Objec } for (ObjectStreamField fieldDesc : fields) { - Field field = classDesc.getReflectionField(fieldDesc); - if (field != null && Modifier.isTransient(field.getModifiers())) { - field = null; // No setting transient fields! (http://b/4471249) - } - // We may not have been able to find the field, or it may be transient, but we still - // need to read the value and do the other checking... + // checkAndGetReflectionField() can return null if it was not able to find the field or + // if it is transient or static. We still need to read the data and do the other + // checking... + Field field = classDesc.checkAndGetReflectionField(fieldDesc); try { Class<?> type = fieldDesc.getTypeInternal(); if (type == byte.class) { diff --git a/luni/src/main/java/java/io/ObjectOutputStream.java b/luni/src/main/java/java/io/ObjectOutputStream.java index 5ab3547..6a2fbed 100644 --- a/luni/src/main/java/java/io/ObjectOutputStream.java +++ b/luni/src/main/java/java/io/ObjectOutputStream.java @@ -950,9 +950,11 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, Ob for (ObjectStreamField fieldDesc : classDesc.fields()) { try { Class<?> type = fieldDesc.getTypeInternal(); - Field field = classDesc.getReflectionField(fieldDesc); + Field field = classDesc.checkAndGetReflectionField(fieldDesc); if (field == null) { - throw new InvalidClassException(classDesc.getName() + " doesn't have a field " + fieldDesc.getName() + " of type " + type); + throw new InvalidClassException(classDesc.getName() + + " doesn't have a serializable field " + fieldDesc.getName() + + " of type " + type); } if (type == byte.class) { output.writeByte(field.getByte(obj)); @@ -1750,7 +1752,7 @@ public class ObjectOutputStream extends OutputStream implements ObjectOutput, Ob // Only write field "name" for enum class, which is the second field of // enum, that is fields[1]. Ignore all non-fields and fields.length < 2 if (fields != null && fields.length > 1) { - Field field = classDesc.getSuperclass().getReflectionField(fields[1]); + Field field = classDesc.getSuperclass().checkAndGetReflectionField(fields[1]); if (field == null) { throw new NoSuchFieldError(); } diff --git a/luni/src/main/java/java/io/ObjectStreamClass.java b/luni/src/main/java/java/io/ObjectStreamClass.java index 9b7f2c9..1a27c9d 100644 --- a/luni/src/main/java/java/io/ObjectStreamClass.java +++ b/luni/src/main/java/java/io/ObjectStreamClass.java @@ -185,26 +185,46 @@ public class ObjectStreamClass implements Serializable { return constructor; } - Field getReflectionField(ObjectStreamField osf) { + /** + * Returns the {@link Field} referred to by {@link ObjectStreamField} for the class described by + * this {@link ObjectStreamClass}. A {@code null} value is returned if the local definition of + * the field does not meet the criteria for a serializable / deserializable field, i.e. the + * field must be non-static and non-transient. Caching of each field lookup is performed. The + * first time a field is returned it is made accessible with a call to + * {@link Field#setAccessible(boolean)}. + */ + Field checkAndGetReflectionField(ObjectStreamField osf) { synchronized (reflectionFields) { Field field = reflectionFields.get(osf); - if (field != null) { + // null might indicate a cache miss or a hit and a non-serializable field so we + // check for a mapping. + if (field != null || reflectionFields.containsKey(osf)) { return field; } } + Field field; try { Class<?> declaringClass = forClass(); - Field field = declaringClass.getDeclaredField(osf.getName()); - field.setAccessible(true); - synchronized (reflectionFields) { - reflectionFields.put(osf, field); + field = declaringClass.getDeclaredField(osf.getName()); + + int modifiers = field.getModifiers(); + if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) { + // No serialization or deserialization of transient or static fields! + // See http://b/4471249 and http://b/17202597. + field = null; + } else { + field.setAccessible(true); } - return reflectionFields.get(osf); } catch (NoSuchFieldException ex) { // The caller messed up. We'll return null and won't try to resolve this again. - return null; + field = null; + } + + synchronized (reflectionFields) { + reflectionFields.put(osf, field); } + return field; } /* |