{"record":{"id":"eb8d05528e401a24","repo":"skylot/jadx","slug":"fail-to-resolve-jsr-instructions","errorCode":null,"errorMessage":"Fail to resolve jsr instructions","messagePattern":"Fail to resolve jsr instructions","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"warning","filePath":"jadx-core/src/main/java/jadx/core/dex/visitors/blocks/ResolveJavaJSR.java","lineNumber":32,"sourceCode":"import jadx.core.utils.exceptions.JadxRuntimeException;\n\n/**\n * Duplicate code to resolve java jsr/ret.\n * JSR (jump subroutine) allows executing the same code from different places.\n * Used mostly for 'finally' blocks, deprecated in Java 7.\n */\npublic class ResolveJavaJSR {\n\n\tpublic static void process(MethodNode mth) {\n\t\tint blocksCount = mth.getBasicBlocks().size();\n\t\tint k = 0;\n\t\twhile (true) {\n\t\t\tboolean changed = resolve(mth);\n\t\t\tif (!changed) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (k++ > blocksCount) {\n\t\t\t\tthrow new JadxRuntimeException(\"Fail to resolve jsr instructions\");\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static boolean resolve(MethodNode mth) {\n\t\tList<BlockNode> blocks = mth.getBasicBlocks();\n\t\tint blocksCount = blocks.size();\n\t\tfor (BlockNode block : blocks) {\n\t\t\tif (BlockUtils.checkLastInsnType(block, InsnType.JAVA_RET)) {\n\t\t\t\tresolveForRetBlock(mth, block);\n\t\t\t\tif (blocksCount != mth.getBasicBlocks().size()) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/dex/visitors/blocks/ResolveJavaJSR.java#L14-L50","documentation":"Thrown during JSR/RET subroutine resolution. JSR (Jump SubRoutine) is a deprecated Java bytecode instruction used for finally blocks. Jadx resolves it by duplicating subroutine code for each call site iteratively. If the resolution doesn't converge within blocksCount iterations, the subroutine structure is too complex to unwind.","triggerScenarios":"The resolve() method returns true (changed) more than blocksCount times, meaning each iteration adds or modifies blocks but never reaches a fixed point. The subroutine pattern creates a non-terminating expansion.","commonSituations":"Legacy Java bytecode (pre-Java 7) with deeply nested or mutually recursive JSR subroutines; obfuscated code that uses JSR-like patterns synthetically; DEX files converted from old class files that retain JSR instructions.","solutions":["Update jadx — JSR resolution has historical edge cases that get patched periodically","Report the class file as a jadx issue — JSR resolution failures are rare and worth investigating","If the input is a .class file, try recompiling or converting with a modern compiler first","Exclude the class if JSR-based finally blocks are not critical to analysis"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Check if input class files use legacy JSR instructions before decompiling\n// JSR/RET are deprecated since Java 6, removed in Java 7+ class file versions\ntry {\n    ClassReader cr = new ClassReader(Files.readAllBytes(classFile.toPath()));\n    if (cr.readByte(6) < 51) { // major version < 51 (Java 7)\n        LOG.info(\"Legacy class file (pre-Java 7) may contain JSR instructions\");\n    }\n} catch (Exception ignored) {}","typeGuard":null,"tryCatchPattern":"try {\n    jadxDecompiler.load();\n    jadxDecompiler.save();\n} catch (JadxRuntimeException e) {\n    if (e.getMessage().contains(\"Fail to resolve jsr instructions\")) {\n        LOG.warn(\"JSR/RET subroutine too complex to resolve, skipping class\");\n        for (ClassNode cls : jadxDecompiler.getClasses()) {\n            try {\n                jadxDecompiler.decompileClass(cls);\n            } catch (JadxRuntimeException ex) {\n                LOG.warn(\"Skipped: {}\", cls.getFullName());\n            }\n        }\n    } else {\n        throw e;\n    }\n}","preventionTips":["For .class file inputs, recompile with a modern compiler (Java 7+) to eliminate JSR","Convert legacy class files through a modern toolchain before decompiling","Keep jadx updated — JSR resolution has historical edge cases that get patched","Exclude classes with known JSR patterns if finally-block analysis is not critical"],"tags":["jsr-ret","subroutine","legacy-bytecode","block-processing","decompiler"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}