{"record":{"id":"02cd8bd08d74cb36","repo":"Tencent/tinker","slug":"string-more-than-65535-utf-bytes-long","errorCode":null,"errorMessage":"String more than 65535 UTF bytes long","messagePattern":"String more than 65535 UTF bytes long","errorType":"exception","errorClass":"UTFDataFormatException","httpStatus":null,"severity":"error","filePath":"third-party/aosp-dexutils/src/main/java/com/tencent/tinker/android/dex/Mutf8.java","lineNumber":79,"sourceCode":"    }\n\n    /**\n     * Returns the number of bytes the modified UTF8 representation of 's' would take.\n     */\n    public static long countBytes(String s, boolean shortLength) throws UTFDataFormatException {\n        long result = 0;\n        final int length = s.length();\n        for (int i = 0; i < length; ++i) {\n            char ch = s.charAt(i);\n            if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.\n                ++result;\n            } else if (ch <= 2047) {\n                result += 2;\n            } else {\n                result += 3;\n            }\n            if (shortLength && result > 65535) {\n                throw new UTFDataFormatException(\"String more than 65535 UTF bytes long\");\n            }\n        }\n        return result;\n    }\n\n    /**\n     * Encodes the modified UTF-8 bytes corresponding to {@code s} into  {@code\n     * dst}, starting at {@code offset}.\n     */\n    public static void encode(byte[] dst, int offset, String s) {\n        final int length = s.length();\n        for (int i = 0; i < length; i++) {\n            char ch = s.charAt(i);\n            if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.\n                dst[offset++] = (byte) ch;\n            } else if (ch <= 2047) {\n                dst[offset++] = (byte) (0xc0 | (0x1f & (ch >> 6)));\n                dst[offset++] = (byte) (0x80 | (0x3f & ch));","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/third-party/aosp-dexutils/src/main/java/com/tencent/tinker/android/dex/Mutf8.java#L61-L97","documentation":"Thrown by Mutf8.countBytes(s, shortLength=true) when the MUTF-8 byte length of a string exceeds 65,535. Dex string_data_item stores utf16_size and the byte data is bounded by a u16-length world; Tinker's copy enforces this while counting, before writing. Only strings ≥64KiB of encoded bytes trip it.","triggerScenarios":"Writing/merging dexes containing an extremely long string constant (huge generated SQL, embedded base64 blobs, long JSON in a string pool) via DexProfile/Dex merger paths that call countBytes with shortLength=true.","commonSituations":"Code generators or ORM/schema tools that embed large literals; JSON/base64 config constants growing past 64KiB after a feature change; merge tools concatenating resource-ish strings into one entry.","solutions":["Split the giant constant into smaller chunks (string array or StringBuilder concatenation) so no single pool string exceeds ~64KiB of MUTF-8 bytes.","If the string is data, move it out of the dex into an asset/resource file and load at runtime.","Re-check with the source toolchain (d8 will emit its own diagnostic pointing at the offending constant) to locate which string blew the limit."],"exampleFix":"// before\nprivate static final String BIG = \"...80KB of base64...\"; // one pool string\n\n// after\nprivate static final String[] BIG_PARTS = {\"...32KB...\", \"...32KB...\", \"...16KB...\"};\nprivate static String big() { return String.join(\"\", BIG_PARTS); }","handlingStrategy":"validation","validationCode":"long bytes = Mutf8.countBytes(candidate, false);\nif (bytes > 65535) throw new IllegalArgumentException(\"string constant too large for dex pool: \" + bytes + \" bytes\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lint generated code for oversized string literals (any constant near 60KB encoded is a smell).","Store large payloads as assets/resources, never as single string-pool entries."],"tags":["dex","mutf8","string-limit","code-generation","tinker"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}