提交 fa996007 编写于 作者: M mduigou

6565585: Remove critical section in Method.invoke, Constructor.newInstance,...

6565585: Remove critical section in Method.invoke, Constructor.newInstance, Field.getFieldAccessor improving performance
Reviewed-by: alanb, dholmes, briangoetz
上级 7f1407a5
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
package java.lang.reflect; package java.lang.reflect;
import java.security.AccessController; import java.security.AccessController;
import sun.reflect.Reflection;
import sun.reflect.ReflectionFactory; import sun.reflect.ReflectionFactory;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
...@@ -201,4 +202,73 @@ public class AccessibleObject implements AnnotatedElement { ...@@ -201,4 +202,73 @@ public class AccessibleObject implements AnnotatedElement {
public Annotation[] getDeclaredAnnotations() { public Annotation[] getDeclaredAnnotations() {
throw new AssertionError("All subclasses should override this method"); throw new AssertionError("All subclasses should override this method");
} }
// Shared access checking logic.
// For non-public members or members in package-private classes,
// it is necessary to perform somewhat expensive security checks.
// If the security check succeeds for a given class, it will
// always succeed (it is not affected by the granting or revoking
// of permissions); we speed up the check in the common case by
// remembering the last Class for which the check succeeded.
//
// The simple security check for Constructor is to see if
// the caller has already been seen, verified, and cached.
// (See also Class.newInstance(), which uses a similar method.)
//
// A more complicated security check cache is needed for Method and Field
// The cache can be either null (empty cache), a 2-array of {caller,target},
// or a caller (with target implicitly equal to this.clazz).
// In the 2-array case, the target is always different from the clazz.
volatile Object securityCheckCache;
void checkAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers)
throws IllegalAccessException
{
if (caller == clazz) { // quick check
return; // ACCESS IS OK
}
Object cache = securityCheckCache; // read volatile
Class<?> targetClass = clazz;
if (obj != null
&& Modifier.isProtected(modifiers)
&& ((targetClass = obj.getClass()) != clazz)) {
// Must match a 2-list of { caller, targetClass }.
if (cache instanceof Class[]) {
Class<?>[] cache2 = (Class<?>[]) cache;
if (cache2[1] == targetClass &&
cache2[0] == caller) {
return; // ACCESS IS OK
}
// (Test cache[1] first since range check for [1]
// subsumes range check for [0].)
}
} else if (cache == caller) {
// Non-protected case (or obj.class == this.clazz).
return; // ACCESS IS OK
}
// If no return, fall through to the slow path.
slowCheckMemberAccess(caller, clazz, obj, modifiers, targetClass);
}
// Keep all this slow stuff out of line:
void slowCheckMemberAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers,
Class<?> targetClass)
throws IllegalAccessException
{
Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);
// Success: Update the cache.
Object cache = ((targetClass == clazz)
? caller
: new Class<?>[] { caller, targetClass });
// Note: The two cache elements are not volatile,
// but they are effectively final. The Java memory model
// guarantees that the initializing stores for the cache
// elements will occur before the volatile write.
securityCheckCache = cache; // write volatile
}
} }
...@@ -74,14 +74,6 @@ public final ...@@ -74,14 +74,6 @@ public final
private byte[] annotations; private byte[] annotations;
private byte[] parameterAnnotations; private byte[] parameterAnnotations;
// For non-public members or members in package-private classes,
// it is necessary to perform somewhat expensive security checks.
// If the security check succeeds for a given class, it will
// always succeed (it is not affected by the granting or revoking
// of permissions); we speed up the check in the common case by
// remembering the last Class for which the check succeeded.
private volatile Class<?> securityCheckCache;
// Generics infrastructure // Generics infrastructure
// Accessor for factory // Accessor for factory
private GenericsFactory getFactory() { private GenericsFactory getFactory() {
...@@ -518,16 +510,17 @@ public final ...@@ -518,16 +510,17 @@ public final
if (!override) { if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass(2); Class<?> caller = Reflection.getCallerClass(2);
if (securityCheckCache != caller) {
Reflection.ensureMemberAccess(caller, clazz, null, modifiers); checkAccess(caller, clazz, null, modifiers);
securityCheckCache = caller;
}
} }
} }
if ((clazz.getModifiers() & Modifier.ENUM) != 0) if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects"); throw new IllegalArgumentException("Cannot reflectively create enum objects");
if (constructorAccessor == null) acquireConstructorAccessor(); ConstructorAccessor ca = constructorAccessor; // read volatile
return (T) constructorAccessor.newInstance(initargs); if (ca == null) {
ca = acquireConstructorAccessor();
}
return (T) ca.newInstance(initargs);
} }
/** /**
...@@ -560,18 +553,20 @@ public final ...@@ -560,18 +553,20 @@ public final
// ConstructorAccessor for a given Constructor. However, avoiding // ConstructorAccessor for a given Constructor. However, avoiding
// synchronization will probably make the implementation more // synchronization will probably make the implementation more
// scalable. // scalable.
private void acquireConstructorAccessor() { private ConstructorAccessor acquireConstructorAccessor() {
// First check to see if one has been created yet, and take it // First check to see if one has been created yet, and take it
// if so. // if so.
ConstructorAccessor tmp = null; ConstructorAccessor tmp = null;
if (root != null) tmp = root.getConstructorAccessor(); if (root != null) tmp = root.getConstructorAccessor();
if (tmp != null) { if (tmp != null) {
constructorAccessor = tmp; constructorAccessor = tmp;
return; } else {
// Otherwise fabricate one and propagate it up to the root
tmp = reflectionFactory.newConstructorAccessor(this);
setConstructorAccessor(tmp);
} }
// Otherwise fabricate one and propagate it up to the root
tmp = reflectionFactory.newConstructorAccessor(this); return tmp;
setConstructorAccessor(tmp);
} }
// Returns ConstructorAccessor for this Constructor object, not // Returns ConstructorAccessor for this Constructor object, not
......
...@@ -79,11 +79,6 @@ class Field extends AccessibleObject implements Member { ...@@ -79,11 +79,6 @@ class Field extends AccessibleObject implements Member {
// potentially many Field objects pointing to it.) // potentially many Field objects pointing to it.)
private Field root; private Field root;
// More complicated security check cache needed here than for
// Class.newInstance() and Constructor.newInstance()
private Class<?> securityCheckCache;
private Class<?> securityCheckTargetClassCache;
// Generics infrastructure // Generics infrastructure
private String getGenericSignature() {return signature;} private String getGenericSignature() {return signature;}
...@@ -954,6 +949,7 @@ class Field extends AccessibleObject implements Member { ...@@ -954,6 +949,7 @@ class Field extends AccessibleObject implements Member {
tmp = reflectionFactory.newFieldAccessor(this, overrideFinalCheck); tmp = reflectionFactory.newFieldAccessor(this, overrideFinalCheck);
setFieldAccessor(tmp, overrideFinalCheck); setFieldAccessor(tmp, overrideFinalCheck);
} }
return tmp; return tmp;
} }
...@@ -983,21 +979,8 @@ class Field extends AccessibleObject implements Member { ...@@ -983,21 +979,8 @@ class Field extends AccessibleObject implements Member {
if (!override) { if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass(4); Class<?> caller = Reflection.getCallerClass(4);
Class<?> targetClass = ((obj == null || !Modifier.isProtected(modifiers))
? clazz
: obj.getClass());
synchronized (this) { checkAccess(caller, clazz, obj, modifiers);
if ((securityCheckCache == caller)
&& (securityCheckTargetClassCache == targetClass)) {
return;
}
}
Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);
synchronized (this) {
securityCheckCache = caller;
securityCheckTargetClassCache = targetClass;
}
} }
} }
} }
......
...@@ -83,11 +83,6 @@ public final ...@@ -83,11 +83,6 @@ public final
// potentially many Method objects pointing to it.) // potentially many Method objects pointing to it.)
private Method root; private Method root;
// More complicated security check cache needed here than for
// Class.newInstance() and Constructor.newInstance()
private Class<?> securityCheckCache;
private Class<?> securityCheckTargetClassCache;
// Generics infrastructure // Generics infrastructure
private String getGenericSignature() {return signature;} private String getGenericSignature() {return signature;}
...@@ -402,28 +397,28 @@ public final ...@@ -402,28 +397,28 @@ public final
*/ */
public String toString() { public String toString() {
try { try {
StringBuffer sb = new StringBuffer(); StringBuilder sb = new StringBuilder();
int mod = getModifiers() & Modifier.methodModifiers(); int mod = getModifiers() & Modifier.methodModifiers();
if (mod != 0) { if (mod != 0) {
sb.append(Modifier.toString(mod) + " "); sb.append(Modifier.toString(mod)).append(' ');
} }
sb.append(Field.getTypeName(getReturnType()) + " "); sb.append(Field.getTypeName(getReturnType())).append(' ');
sb.append(Field.getTypeName(getDeclaringClass()) + "."); sb.append(Field.getTypeName(getDeclaringClass())).append('.');
sb.append(getName() + "("); sb.append(getName()).append('(');
Class<?>[] params = parameterTypes; // avoid clone Class<?>[] params = parameterTypes; // avoid clone
for (int j = 0; j < params.length; j++) { for (int j = 0; j < params.length; j++) {
sb.append(Field.getTypeName(params[j])); sb.append(Field.getTypeName(params[j]));
if (j < (params.length - 1)) if (j < (params.length - 1))
sb.append(","); sb.append(',');
} }
sb.append(")"); sb.append(')');
Class<?>[] exceptions = exceptionTypes; // avoid clone Class<?>[] exceptions = exceptionTypes; // avoid clone
if (exceptions.length > 0) { if (exceptions.length > 0) {
sb.append(" throws "); sb.append(" throws ");
for (int k = 0; k < exceptions.length; k++) { for (int k = 0; k < exceptions.length; k++) {
sb.append(exceptions[k].getName()); sb.append(exceptions[k].getName());
if (k < (exceptions.length - 1)) if (k < (exceptions.length - 1))
sb.append(","); sb.append(',');
} }
} }
return sb.toString(); return sb.toString();
...@@ -475,15 +470,15 @@ public final ...@@ -475,15 +470,15 @@ public final
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
int mod = getModifiers() & Modifier.methodModifiers(); int mod = getModifiers() & Modifier.methodModifiers();
if (mod != 0) { if (mod != 0) {
sb.append(Modifier.toString(mod) + " "); sb.append(Modifier.toString(mod)).append(' ');
} }
TypeVariable<?>[] typeparms = getTypeParameters(); TypeVariable<?>[] typeparms = getTypeParameters();
if (typeparms.length > 0) { if (typeparms.length > 0) {
boolean first = true; boolean first = true;
sb.append("<"); sb.append('<');
for(TypeVariable<?> typeparm: typeparms) { for(TypeVariable<?> typeparm: typeparms) {
if (!first) if (!first)
sb.append(","); sb.append(',');
// Class objects can't occur here; no need to test // Class objects can't occur here; no need to test
// and call Class.getName(). // and call Class.getName().
sb.append(typeparm.toString()); sb.append(typeparm.toString());
...@@ -494,10 +489,11 @@ public final ...@@ -494,10 +489,11 @@ public final
Type genRetType = getGenericReturnType(); Type genRetType = getGenericReturnType();
sb.append( ((genRetType instanceof Class<?>)? sb.append( ((genRetType instanceof Class<?>)?
Field.getTypeName((Class<?>)genRetType):genRetType.toString()) + " "); Field.getTypeName((Class<?>)genRetType):genRetType.toString()))
.append(' ');
sb.append(Field.getTypeName(getDeclaringClass()) + "."); sb.append(Field.getTypeName(getDeclaringClass())).append('.');
sb.append(getName() + "("); sb.append(getName()).append('(');
Type[] params = getGenericParameterTypes(); Type[] params = getGenericParameterTypes();
for (int j = 0; j < params.length; j++) { for (int j = 0; j < params.length; j++) {
String param = (params[j] instanceof Class)? String param = (params[j] instanceof Class)?
...@@ -507,9 +503,9 @@ public final ...@@ -507,9 +503,9 @@ public final
param = param.replaceFirst("\\[\\]$", "..."); param = param.replaceFirst("\\[\\]$", "...");
sb.append(param); sb.append(param);
if (j < (params.length - 1)) if (j < (params.length - 1))
sb.append(","); sb.append(',');
} }
sb.append(")"); sb.append(')');
Type[] exceptions = getGenericExceptionTypes(); Type[] exceptions = getGenericExceptionTypes();
if (exceptions.length > 0) { if (exceptions.length > 0) {
sb.append(" throws "); sb.append(" throws ");
...@@ -518,7 +514,7 @@ public final ...@@ -518,7 +514,7 @@ public final
((Class)exceptions[k]).getName(): ((Class)exceptions[k]).getName():
exceptions[k].toString()); exceptions[k].toString());
if (k < (exceptions.length - 1)) if (k < (exceptions.length - 1))
sb.append(","); sb.append(',');
} }
} }
return sb.toString(); return sb.toString();
...@@ -591,26 +587,15 @@ public final ...@@ -591,26 +587,15 @@ public final
if (!override) { if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass(1); Class<?> caller = Reflection.getCallerClass(1);
Class<?> targetClass = ((obj == null || !Modifier.isProtected(modifiers))
? clazz checkAccess(caller, clazz, obj, modifiers);
: obj.getClass());
boolean cached;
synchronized (this) {
cached = (securityCheckCache == caller)
&& (securityCheckTargetClassCache == targetClass);
}
if (!cached) {
Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);
synchronized (this) {
securityCheckCache = caller;
securityCheckTargetClassCache = targetClass;
}
}
} }
} }
if (methodAccessor == null) acquireMethodAccessor(); MethodAccessor ma = methodAccessor; // read volatile
return methodAccessor.invoke(obj, args); if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
} }
/** /**
...@@ -654,18 +639,20 @@ public final ...@@ -654,18 +639,20 @@ public final
// (though not efficient) to generate more than one MethodAccessor // (though not efficient) to generate more than one MethodAccessor
// for a given Method. However, avoiding synchronization will // for a given Method. However, avoiding synchronization will
// probably make the implementation more scalable. // probably make the implementation more scalable.
private void acquireMethodAccessor() { private MethodAccessor acquireMethodAccessor() {
// First check to see if one has been created yet, and take it // First check to see if one has been created yet, and take it
// if so // if so
MethodAccessor tmp = null; MethodAccessor tmp = null;
if (root != null) tmp = root.getMethodAccessor(); if (root != null) tmp = root.getMethodAccessor();
if (tmp != null) { if (tmp != null) {
methodAccessor = tmp; methodAccessor = tmp;
return; } else {
// Otherwise fabricate one and propagate it up to the root
tmp = reflectionFactory.newMethodAccessor(this);
setMethodAccessor(tmp);
} }
// Otherwise fabricate one and propagate it up to the root
tmp = reflectionFactory.newMethodAccessor(this); return tmp;
setMethodAccessor(tmp);
} }
// Returns MethodAccessor for this Method object, not looking up // Returns MethodAccessor for this Method object, not looking up
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册