FYI: Another AccessController speedup
Gary Benson
gbenson@redhat.com
Thu Aug 10 10:12:00 GMT 2006
Hi all,
When I first mailed the AccessController patch for comments Andrew
Haley pointed out that for every method a string is created solely
to be compared with "doPrivileged" and then thrown away. This
commit gets rid of all that. On my Tomcat benchmark this improves
performance from 2100 to 2200 requests per second.
Cheers,
Gary
-------------- next part --------------
Index: ChangeLog
===================================================================
--- ChangeLog (revision 116038)
+++ ChangeLog (working copy)
@@ -1,3 +1,16 @@
+2006-08-10 Gary Benson <gbenson@redhat.com>
+
+ * include/java-stack.h (GetAccessControlStack): Change return
+ type.
+ * stacktrace.cc (accesscontrol_trace_fn): Record the number of
+ Java frames encountered.
+ (GetAccessControlStack): Return a flag indicating whether a call to
+ doPrivileged was encountered rather than an array of method names.
+ * java/security/natVMAccessController.cc (getStack): Change return
+ type.
+ * java/security/VMAccessController.java (getStack): Likewise.
+ (getContext): Change to reflect the above.
+
2006-08-09 Gary Benson <gbenson@redhat.com>
* stacktrace.cc (accesscontrol_trace_fn): Skip non-Java frames.
Index: include/java-stack.h
===================================================================
--- include/java-stack.h (revision 116033)
+++ include/java-stack.h (working copy)
@@ -125,7 +125,7 @@
static void GetCallerInfo (jclass checkClass, jclass *, _Jv_Method **);
static JArray<jclass> *GetClassContext (jclass checkClass);
static ClassLoader *GetFirstNonSystemClassLoader (void);
- static JArray<jobjectArray> *GetAccessControlStack ();
+ static jobjectArray GetAccessControlStack ();
};
Index: stacktrace.cc
===================================================================
--- stacktrace.cc (revision 116038)
+++ stacktrace.cc (working copy)
@@ -18,6 +18,7 @@
#include <stdio.h>
+#include <java/lang/Boolean.h>
#include <java/lang/Class.h>
#include <java/lang/Long.h>
#include <java/security/AccessController.h>
@@ -536,59 +537,58 @@
return NULL;
}
+struct AccessControlTraceData
+{
+ jint length;
+ jboolean privileged;
+};
+
_Unwind_Reason_Code
_Jv_StackTrace::accesscontrol_trace_fn (_Jv_UnwindState *state)
{
+ AccessControlTraceData *trace_data = (AccessControlTraceData *)
+ state->trace_data;
_Jv_StackFrame *frame = &state->frames[state->pos];
FillInFrameInfo (frame);
if (!(frame->klass && frame->meth))
return _URC_NO_REASON;
- bool *stopping = (bool *) state->trace_data;
- if (*stopping)
+ trace_data->length++;
+
+ // If the previous frame was a call to doPrivileged, then this is
+ // the last frame we look at.
+ if (trace_data->privileged)
return _URC_NORMAL_STOP;
if (frame->klass == &::java::security::AccessController::class$
&& strcmp (frame->meth->name->chars(), "doPrivileged") == 0)
- *stopping = true;
+ trace_data->privileged = true;
return _URC_NO_REASON;
}
-JArray<jobjectArray> *
+jobjectArray
_Jv_StackTrace::GetAccessControlStack (void)
{
int trace_size = 100;
_Jv_StackFrame frames[trace_size];
_Jv_UnwindState state (trace_size);
state.frames = (_Jv_StackFrame *) &frames;
+
+ AccessControlTraceData trace_data;
+ trace_data.length = 0;
+ trace_data.privileged = false;
+
state.trace_function = accesscontrol_trace_fn;
- bool stopping = false;
- state.trace_data = (void *) &stopping;
+ state.trace_data = (void *) &trace_data;
UpdateNCodeMap();
_Unwind_Backtrace (UnwindTraceFn, &state);
-
- jint length = 0;
- for (int i = 0; i < state.pos; i++)
- {
- _Jv_StackFrame *frame = &state.frames[i];
-
- if (frame->klass && frame->meth)
- length++;
- }
-
- jclass array_class = _Jv_GetArrayClass (&::java::lang::Object::class$, NULL);
- JArray<jobjectArray> *result =
- (JArray<jobjectArray> *) _Jv_NewObjectArray (2, array_class, NULL);
JArray<jclass> *classes = (JArray<jclass> *)
- _Jv_NewObjectArray (length, &::java::lang::Class::class$, NULL);
- JArray<jstring> *methods = (JArray<jstring> *)
- _Jv_NewObjectArray (length, &::java::lang::String::class$, NULL);
- jclass *c = elements (classes);
- jstring *m = elements (methods);
+ _Jv_NewObjectArray (trace_data.length, &::java::lang::Class::class$, NULL);
+ jclass *c = elements (classes);
for (int i = 0, j = 0; i < state.pos; i++)
{
@@ -596,13 +596,15 @@
if (!frame->klass || !frame->meth)
continue;
c[j] = frame->klass;
- m[j] = JvNewStringUTF (frame->meth->name->chars());
j++;
}
- jobjectArray *elems = elements (result);
- elems[0] = (jobjectArray) classes;
- elems[1] = (jobjectArray) methods;
-
+ jobjectArray result =
+ (jobjectArray) _Jv_NewObjectArray (2, &::java::lang::Object::class$,
+ NULL);
+ jobject *r = elements (result);
+ r[0] = (jobject) classes;
+ r[1] = (jobject) new Boolean (trace_data.privileged);
+
return result;
}
Index: java/security/natVMAccessController.cc
===================================================================
--- java/security/natVMAccessController.cc (revision 116033)
+++ java/security/natVMAccessController.cc (working copy)
@@ -16,7 +16,7 @@
#include <java/security/VMAccessController.h>
-JArray<jobjectArray> *
+jobjectArray
java::security::VMAccessController::getStack ()
{
return _Jv_StackTrace::GetAccessControlStack ();
Index: java/security/VMAccessController.java
===================================================================
--- java/security/VMAccessController.java (revision 116033)
+++ java/security/VMAccessController.java (working copy)
@@ -178,9 +178,9 @@
inGetContext.set(Boolean.TRUE);
- Object[][] stack = getStack();
+ Object[] stack = getStack();
Class[] classes = (Class[]) stack[0];
- String[] methods = (String[]) stack[1];
+ boolean privileged = ((Boolean) stack[1]).booleanValue();
if (DEBUG)
debug("got trace of length " + classes.length);
@@ -188,32 +188,24 @@
HashSet domains = new HashSet();
HashSet seenDomains = new HashSet();
AccessControlContext context = null;
- int privileged = 0;
// We walk down the stack, adding each ProtectionDomain for each
// class in the call stack. If we reach a call to doPrivileged,
// we don't add any more stack frames. We skip the first three stack
// frames, since they comprise the calls to getStack, getContext,
// and AccessController.getContext.
- for (int i = 3; i < classes.length && privileged < 2; i++)
+ for (int i = 3; i < classes.length; i++)
{
Class clazz = classes[i];
- String method = methods[i];
if (DEBUG)
{
- debug("checking " + clazz + "." + method);
+ debug("checking " + clazz);
// subject to getClassLoader RuntimePermission
debug("loader = " + clazz.getClassLoader());
}
- // If the previous frame was a call to doPrivileged, then this is
- // the last frame we look at.
- if (privileged == 1)
- privileged = 2;
-
- if (clazz.equals (AccessController.class)
- && method.equals ("doPrivileged"))
+ if (privileged && i == classes.length - 2)
{
// If there was a call to doPrivileged with a supplied context,
// return that context. If using JAAS doAs*, it should be
@@ -221,7 +213,6 @@
LinkedList l = (LinkedList) contexts.get();
if (l != null)
context = (AccessControlContext) l.getFirst();
- privileged = 1;
}
// subject to getProtectionDomain RuntimePermission
@@ -270,16 +261,14 @@
}
/**
- * Returns a snapshot of the current call stack as a pair of arrays:
- * the first an array of classes in the call stack, the second an array
- * of strings containing the method names in the call stack. The two
- * arrays match up, meaning that method <i>i</i> is declared in class
- * <i>i</i>. The arrays are clean; it will only contain Java methods,
- * and no element of the list should be null.
+ * Returns a snapshot of the current call stack as a two-element
+ * array. The first element is an array of classes in the call
+ * stack, and the second element is a boolean value indicating
+ * whether the trace stopped early because a call to doPrivileged
+ * was encountered. If this boolean value is true then the call to
+ * doPrivileged will be the second-last frame in the returned trace.
*
- * @return A pair of arrays describing the current call stack. The first
- * element is an array of Class objects, and the second is an array
- * of Strings comprising the method names.
+ * @return A snapshot of the current call stack.
*/
- private static native Object[][] getStack();
+ private static native Object[] getStack();
}
More information about the Java-patches
mailing list