// immutable, has strong refs // Do not run in a synchronized block - it goes wrong in the presence // of elaborate classloaders (like in Gazelle BEA) // see #1102990 and #1102991 final sclass _MethodCache { final Class c; final HashMap> cache = new HashMap; *(Class *c) { _init(); } void _init() { Class _c = c; java.lang.Module myModule = getClass().getModule(); bool anyHiddenClasses; while (_c != null) { bool exported = classIsExportedTo(_c, myModule); printVars ifdef _MethodCache_debug("_MethodCache._init", +_c, +exported); if (!exported) set anyHiddenClasses; else for (Method m : _c.getDeclaredMethods()) if ((anyHiddenClasses || !isAbstract(m)) && !reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); _c = _c.getSuperclass(); } // add default methods - this might lead to a duplication // because the overridden method is also added, but it's not // a problem except for minimal performance loss. // If any classes in the hierarchy were inaccessible, we add // all interface methods (see test_callForbiddenMethodByReflection for a test) for (Class intf : allInterfacesImplementedBy(c)) for (Method m : intf.getDeclaredMethods()) if ((anyHiddenClasses || m.isDefault()) && !reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); print ifdef _MethodCache_debug("MethodCache " + this + ": " + className(c) + " => " + keys(cache)); } // Returns only matching methods Method findMethod(S method, O[] args) ctex { L m = cache.get(method); print ifdef _MethodCache_debug("findMethod " + this + ": " + className(c) + "/" + method + " => " + m); if (m == null) null; int n = m.size(); for i to n: { Method me = m.get(i); if (call_checkArgs(me, args, false)) ret me; } null; } Method findStaticMethod(S method, O[] args) ctex { L m = cache.get(method); if (m == null) null; int n = m.size(); for i to n: { Method me = m.get(i); if (isStaticMethod(me) && call_checkArgs(me, args, false)) ret me; } null; } //Cl allMethods() { ret allValues(cache); } }