static JavaMembers lookupClass(Scriptable scope, Class dynamicType,
                                   Class staticType, boolean includeProtected)
    {
        JavaMembers members;
        scope = ScriptableObject.getTopLevelScope(scope);
        ClassCache cache = ClassCache.get(scope);
        Map<Class<?>,JavaMembers> ct = cache.getClassCacheMap();

        Class cl = dynamicType;
        for (;;) {
            members = ct.get(cl);
            if (members != null) {
                return members;
            }
            try {
                members = new JavaMembers(scope, cl, includeProtected);
                break;
            } catch (SecurityException e) {
                // Reflection may fail for objects that are in a restricted
                // access package (e.g. sun.*).  If we get a security
                // exception, try again with the static type if it is interface.
                // Otherwise, try superclass
                if (staticType != null && staticType.isInterface()) {
                    cl = staticType;
                    staticType = null; // try staticType only once
                } else {
                    Class parent = cl.getSuperclass();
                    if (parent == null) {
                        if (cl.isInterface()) {
                            // last resort after failed staticType interface
                            parent = ScriptRuntime.ObjectClass;
                        } else {
                            throw e;
                        }
                    }
                    cl = parent;
                }
            }
        }

        if (cache.isCachingEnabled())
            ct.put(cl, members);
        return members;
    }