{"record":{"id":"3a5838b65d944627","repo":"Tencent/tinker","slug":"fail-to-create-tinkerclassloader","errorCode":null,"errorMessage":"Fail to create TinkerClassLoader.","messagePattern":"Fail to create TinkerClassLoader\\.","errorType":"exception","errorClass":"TinkerRuntimeException","httpStatus":null,"severity":"critical","filePath":"tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/TinkerClassLoader.java","lineNumber":87,"sourceCode":"                mOriginAppClassLoader.getResources(name)\n        };\n        return new CompoundEnumeration<>(resources);\n    }\n\n    private static void injectDexPath(ClassLoader cl, String dexPath, File optimizedDir) {\n        try {\n            final List<File> dexFiles = new ArrayList<>(16);\n            for (String oneDexPath : dexPath.split(\":\")) {\n                if (oneDexPath.isEmpty()) {\n                    continue;\n                }\n                dexFiles.add(new File(oneDexPath));\n            }\n            if (!dexFiles.isEmpty()) {\n                SystemClassLoaderAdder.injectDexesInternal(cl, dexFiles, optimizedDir);\n            }\n        } catch (Throwable thr) {\n            throw new TinkerRuntimeException(\"Fail to create TinkerClassLoader.\", thr);\n        }\n    }\n\n    @Keep\n    class CompoundEnumeration<E> implements Enumeration<E> {\n        private Enumeration<E>[] enums;\n        private int index = 0;\n\n        public CompoundEnumeration(Enumeration<E>[] enums) {\n            this.enums = enums;\n        }\n\n        @Override\n        public boolean hasMoreElements() {\n            while (index < enums.length) {\n                if (enums[index] != null && enums[index].hasMoreElements()) {\n                    return true;\n                }","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/TinkerClassLoader.java#L69-L105","documentation":"TinkerClassLoader's constructor splits the dexPath on ':', collects non-empty File entries, and calls SystemClassLoaderAdder.injectDexesInternal to install them into the delegate classloader (which dispatches to V23/V19/V14 per SDK). Any throwable from that injection is wrapped in TinkerRuntimeException('Fail to create TinkerClassLoader.'). It is the aggregate failure point for dex injection on the tinker classloader path.","triggerScenarios":"injectDexesInternal throwing: reflection failures in V14/V19/V23 installers (field/method not found on the OEM framework ClassLoader), illegal dex files, IO errors reading dex/opt files, or odex-writing failures — anything thrown while merging dexElements.","commonSituations":"Older Android versions (V14/V19 path) with OEM-renamed framework internals; malformed dexPath entries; dex optimization failures writing to the optimized directory; storage permission loss between patch apply and load.","solutions":["Log and inspect the wrapped cause (Throwable thr) — NoSuchFieldException/NoSuchMethodException point to framework incompatibility, IOException to file issues.","Confirm every ':'-separated dexPath segment exists, is a legal file (SharePatchFileUtil.isLegalFile) and is readable before constructing the loader.","Upgrade tinker for per-version installer fixes; verify the failing device's Android version is supported.","If cause is storage-related, clean the tinker directory (cleanPatch) so the patch re-applies cleanly next launch."],"exampleFix":"// before\nTinkerClassLoader tcl = new TinkerClassLoader(dexPath, optimizedDir, libraryPath, parent);\n\n// after\nfor (String p : dexPath.split(\":\")) {\n    if (!p.isEmpty() && !SharePatchFileUtil.isLegalFile(new File(p))) {\n        throw new IllegalStateException(\"missing patch dex: \" + p);\n    }\n}\nTinkerClassLoader tcl = new TinkerClassLoader(dexPath, optimizedDir, libraryPath, parent);","handlingStrategy":"validation","validationCode":"for (String p : dexPath.split(\":\")) {\n    if (!p.isEmpty() && !SharePatchFileUtil.isLegalFile(new File(p))) {\n        // refuse to construct loader with missing dex\n    }\n}","typeGuard":null,"tryCatchPattern":"catch TinkerRuntimeException 'Fail to create TinkerClassLoader.' -> read the cause; reflection failures mean unsupported framework (disable patch), IO failures mean cleanPatch + retry","preventionTips":["Validate every dex path segment is a legal file before constructing TinkerClassLoader.","Keep tinker updated for OEM framework variations on V14/V19/V23 injection paths.","Preserve the wrapped cause in crash reporting — the root throwable names the real failure."],"tags":["classloader","dex-injection","reflection","patch-load"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}