
|
If you were logged in you would be able to see more operations.
|
|
|
|
This relates to the OgnlRuntime.invokeMethod.
Version 2.6.11 introduced sychronization on the Method instance for any Class whose instances are being traversed. Method instances, like Class instances, are singletons within a classloader. Net result: no two threads can call method.invoke concurrently, even against two different target object instances. Scalability is completely hosed.
I saw that in the 2.6.10 there could be race conditions on the accessibility permissions of the methods, so it does make sense to synchronize here. But in most high concurrency applications, I'd trade the ability to access private methods for scalability any day.
public static Object invokeMethod( Object target, Method method, Object[] argsArray ) throws InvocationTargetException, IllegalAccessException
{
Object result;
boolean wasAccessible = true;
if (securityManager != null) {
try {
securityManager.checkPermission(getPermission(method));
} catch (SecurityException ex) {
throw new IllegalAccessException("Method [" + method + "] cannot be accessed.");
}
}
synchronized (method) {
if (!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
if (!(wasAccessible = ((AccessibleObject)method).isAccessible())) {
((AccessibleObject)method).setAccessible(true);
}
}
result = method.invoke( target, argsArray );
if (!wasAccessible) {
((AccessibleObject)method).setAccessible(false);
}
}
return result;
}
|
|
Description
|
This relates to the OgnlRuntime.invokeMethod.
Version 2.6.11 introduced sychronization on the Method instance for any Class whose instances are being traversed. Method instances, like Class instances, are singletons within a classloader. Net result: no two threads can call method.invoke concurrently, even against two different target object instances. Scalability is completely hosed.
I saw that in the 2.6.10 there could be race conditions on the accessibility permissions of the methods, so it does make sense to synchronize here. But in most high concurrency applications, I'd trade the ability to access private methods for scalability any day.
public static Object invokeMethod( Object target, Method method, Object[] argsArray ) throws InvocationTargetException, IllegalAccessException
{
Object result;
boolean wasAccessible = true;
if (securityManager != null) {
try {
securityManager.checkPermission(getPermission(method));
} catch (SecurityException ex) {
throw new IllegalAccessException("Method [" + method + "] cannot be accessed.");
}
}
synchronized (method) {
if (!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
if (!(wasAccessible = ((AccessibleObject)method).isAccessible())) {
((AccessibleObject)method).setAccessible(true);
}
}
result = method.invoke( target, argsArray );
if (!wasAccessible) {
((AccessibleObject)method).setAccessible(false);
}
}
return result;
}
|
Show » |
|
A thread waiting to lock
daemon prio=1 tid=0x4e9bf820 nid=0x781 waiting for monitor entry [0x47f2e000..0x47f2fe30]
at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:511)
- waiting to lock <0x6f4bdc88> (a java.lang.reflect.Method)
at ognl.OgnlRuntime.getMethodValue(OgnlRuntime.java:931)
at ognl.ObjectPropertyAccessor.getPossibleProperty(ObjectPropertyAccessor.java:53)
at ognl.ObjectPropertyAccessor.getProperty(ObjectPropertyAccessor.java:121)
at com.opensymphony.xwork.util.OgnlValueStack$ObjectAccessor.getProperty(OgnlValueStack.java:57)
And the initial lock:
prio=1 tid=0x5084c860 nid=0x778 runnable [0x49389000..0x4938ae30]
at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:517)
- locked <0x6f4bdc88> (a java.lang.reflect.Method)
at ognl.OgnlRuntime.getMethodValue(OgnlRuntime.java:931)
at ognl.ObjectPropertyAccessor.getPossibleProperty(ObjectPropertyAccessor.java:53)
at ognl.ObjectPropertyAccessor.getProperty(ObjectPropertyAccessor.java:121)
at com.opensymphony.xwork.util.OgnlValueStack$ObjectAccessor.getProperty(OgnlValueStack.java:57)