public static Object invokeMethod(Object target, Method method, Object[] argsArray)
            throws InvocationTargetException, IllegalAccessException
    {
        boolean syncInvoke = false;
        boolean checkPermission = false;

        // only synchronize method invocation if it actually requires it

        synchronized(method) {
            if (_methodAccessCache.get(method) == null
                || _methodAccessCache.get(method) == Boolean.TRUE) {
                syncInvoke = true;
            }

            if (_securityManager != null && _methodPermCache.get(method) == null
                || _methodPermCache.get(method) == Boolean.FALSE) {
                checkPermission = true;
            }
        }

        Object result;
        boolean wasAccessible = true;

        if (syncInvoke)
        {
            synchronized(method)
            {
                if (checkPermission)
                {
                    try
                    {
                        _securityManager.checkPermission(getPermission(method));
                        _methodPermCache.put(method, Boolean.TRUE);
                    } catch (SecurityException ex) {
                        _methodPermCache.put(method, Boolean.FALSE);
                        throw new IllegalAccessException("Method [" + method + "] cannot be accessed.");
                    }
                }

                if (!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
                {
                    if (!(wasAccessible = ((AccessibleObject) method).isAccessible()))
                    {
                        ((AccessibleObject) method).setAccessible(true);
                        _methodAccessCache.put(method, Boolean.TRUE);
                    } else
                    {
                        _methodAccessCache.put(method, Boolean.FALSE);
                    }
                } else
                {
                    _methodAccessCache.put(method, Boolean.FALSE);
                }

                result = method.invoke(target, argsArray);

                if (!wasAccessible)
                {
                    ((AccessibleObject) method).setAccessible(false);
                }
            }
        } else
        {
            if (checkPermission)
            {
                try
                {
                    _securityManager.checkPermission(getPermission(method));
                    _methodPermCache.put(method, Boolean.TRUE);
                } catch (SecurityException ex) {
                    _methodPermCache.put(method, Boolean.FALSE);
                    throw new IllegalAccessException("Method [" + method + "] cannot be accessed.");
                }
            }

            result = method.invoke(target, argsArray);
        }

        return result;
    }