{"record":{"id":"aff7cba7205bac9a","repo":"didi/DoKit","slug":"oops","errorCode":null,"errorMessage":"Oops!","messagePattern":"Oops!","errorType":"exception","errorClass":"ReflectedException","httpStatus":null,"severity":"error","filePath":"Android/dokit/src/main/java/com/didichuxing/doraemonkit/util/Reflector.java","lineNumber":48,"sourceCode":"        }\n        public ReflectedException(String message, Throwable cause) {\n            super(message, cause);\n        }\n    \n    }\n    public static Reflector on(@NonNull String name) throws ReflectedException {\n        return on(name, true, Reflector.class.getClassLoader());\n    }\n    \n    public static Reflector on(@NonNull String name, boolean initialize) throws ReflectedException {\n        return on(name, initialize, Reflector.class.getClassLoader());\n    }\n    \n    public static Reflector on(@NonNull String name, boolean initialize, @Nullable ClassLoader loader) throws ReflectedException {\n        try {\n            return on(Class.forName(name, initialize, loader));\n        } catch (Throwable e) {\n            throw new ReflectedException(\"Oops!\", e);\n        }\n    }\n    \n    public static Reflector on(@NonNull Class<?> type) {\n        Reflector reflector = new Reflector();\n        reflector.mType = type;\n        return reflector;\n    }\n    \n    public static Reflector with(@NonNull Object caller) throws ReflectedException {\n        return on(caller.getClass()).bind(caller);\n    }\n    \n    protected Reflector() {\n    \n    }\n    \n    public Reflector constructor(@Nullable Class<?>... parameterTypes) throws ReflectedException {","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit/src/main/java/com/didichuxing/doraemonkit/util/Reflector.java#L30-L66","documentation":"Reflector.on(String, boolean, ClassLoader) wraps Class.forName in a try-catch and rethrows any failure as ReflectedException(\"Oops!\", e). The 'Oops!' message is generic; the real cause (usually ClassNotFoundException, or an initialization failure from the static initializer when initialize=true) is attached as the cause. This entry point is how DoraemonKit reflectively loads framework internals that vary across Android OS versions or vendor ROMs.","triggerScenarios":"Calling Reflector.on(\"android.some.InternalClass\") when the class does not exist on the running device (removed/renamed in that API level), when the class is not visible to the supplied ClassLoader, or when initialize=true and the class's static initializer throws.","commonSituations":"Running DoraemonKit on an Android version whose hidden framework classes were refactored; vendor ROMs that strip internals; proguard/R8 renaming obfuscating the target class name; wrong ClassLoader in plugin/embedded environments.","solutions":["Read the attached cause: ClassNotFoundException means the name is wrong for this OS version — guard the call per Build.VERSION.SDK_INT","Pass initialize=false if the class's static initializer is what fails","Verify the fully-qualified class name against the AOSP source for the device's API level","Switch to QuietReflector.on(...) which swallows the failure and exposes mIgnored instead of throwing","If obfuscation renamed the target, add proguard keep rules for the reflected class"],"exampleFix":"// before\nReflector refl = Reflector.on(\"android.app.ActivityThread\");\n\n// after\nif (Build.VERSION.SDK_INT >= 29) {\n    Reflector refl = Reflector.on(\"android.app.ActivityThread\", false);\n} else {\n    Reflector.QuietReflector refl = Reflector.QuietReflector.on(\"android.app.ActivityThread\");\n    // refl.mIgnored != null -> feature unavailable on this device\n}","handlingStrategy":"try-catch","validationCode":"public static boolean classExists(String fqcn, ClassLoader cl) {\n    try {\n        Class.forName(fqcn, false, cl != null ? cl : Reflector.class.getClassLoader());\n        return true;\n    } catch (Throwable t) {\n        return false;\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    Reflector r = Reflector.on(\"android.app.ActivityThread\");\n} catch (ReflectedException e) {\n    Throwable cause = e.getCause(); // usually ClassNotFoundException\n    if (cause instanceof ClassNotFoundException) { /* feature unavailable on this build */ }\n}","preventionTips":["Gate reflective class lookups by Build.VERSION.SDK_INT","Prefer QuietReflector for OS-internal classes","Add proguard keep rules for reflectively accessed classes"],"tags":["reflection","class-loading","android","runtime"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}