summaryrefslogtreecommitdiffstats
path: root/luni/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'luni/src/main')
-rw-r--r--luni/src/main/java/java/io/ObjectInputStream.java11
-rw-r--r--luni/src/main/java/java/io/ObjectOutputStream.java8
-rw-r--r--luni/src/main/java/java/io/ObjectStreamClass.java36
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;
}
/*