8197925: Better stack walking

Reviewed-by: alanb, skoivu, rriggs, igerasim, rhalade, darcy
This commit is contained in:
Stuart Marks 2018-05-31 11:31:20 -07:00
parent 023ee573d3
commit d51ccbc325

View File

@ -87,6 +87,9 @@ public class ReflectionFactory {
private static boolean noInflation = false;
private static int inflationThreshold = 15;
// true if deserialization constructor checking is disabled
private static boolean disableSerialConstructorChecks = false;
private ReflectionFactory() {
}
@ -424,10 +427,64 @@ public class ReflectionFactory {
return generateConstructor(cl, constructorToCall);
}
/**
* Given a class, determines whether its superclass has
* any constructors that are accessible from the class.
* This is a special purpose method intended to do access
* checking for a serializable class and its superclasses
* up to, but not including, the first non-serializable
* superclass. This also implies that the superclass is
* always non-null, because a serializable class must be a
* class (not an interface) and Object is not serializable.
*
* @param cl the class from which access is checked
* @return whether the superclass has a constructor accessible from cl
*/
private boolean superHasAccessibleConstructor(Class<?> cl) {
Class<?> superCl = cl.getSuperclass();
assert Serializable.class.isAssignableFrom(cl);
assert superCl != null;
if (packageEquals(cl, superCl)) {
// accessible if any non-private constructor is found
for (Constructor<?> ctor : superCl.getDeclaredConstructors()) {
if ((ctor.getModifiers() & Modifier.PRIVATE) == 0) {
return true;
}
}
return false;
} else {
// accessible if the parent is public and any constructor
// is protected or public
if ((superCl.getModifiers() & Modifier.PUBLIC) == 0) {
return false;
}
for (Constructor<?> ctor : superCl.getDeclaredConstructors()) {
if ((ctor.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) != 0) {
return true;
}
}
return false;
}
}
/**
* Returns a constructor that allocates an instance of cl and that then initializes
* the instance by calling the no-arg constructor of its first non-serializable
* superclass. This is specified in the Serialization Specification, section 3.1,
* in step 11 of the deserialization process. If cl is not serializable, returns
* cl's no-arg constructor. If no accessible constructor is found, or if the
* class hierarchy is somehow malformed (e.g., a serializable class has no
* superclass), null is returned.
*
* @param cl the class for which a constructor is to be found
* @return the generated constructor, or null if none is available
*/
public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
Class<?> initCl = cl;
while (Serializable.class.isAssignableFrom(initCl)) {
if ((initCl = initCl.getSuperclass()) == null) {
Class<?> prev = initCl;
if ((initCl = initCl.getSuperclass()) == null ||
(!disableSerialConstructorChecks && !superHasAccessibleConstructor(prev))) {
return null;
}
}
@ -653,6 +710,9 @@ public class ReflectionFactory {
}
}
disableSerialConstructorChecks =
"true".equals(props.getProperty("jdk.disableSerialConstructorChecks"));
initted = true;
}