skylot/jadx · warning · CodegenException
Anonymous inner class unlimited recursion detected. Convert
Error message
Anonymous inner class unlimited recursion detected. Convert class to inner:
What it means
Thrown by InsnGen.inlineAnonymousConstructor() when the anonymous class being inlined is the same class as the current method's parent class — meaning infinite recursion would occur if inlining proceeded. Rather than hanging, jadx converts the class from anonymous to a regular inner class (removes ANONYMOUS_CLASS and DONT_GENERATE flags), sets RESTART_CODEGEN to trigger a fresh codegen pass, and throws this CodegenException to unwind the current generation. This is a recovery mechanism, not a terminal error.
Source
Thrown at jadx-core/src/main/java/jadx/core/codegen/InsnGen.java:812
if (instArg.isThis()) {
return false;
}
// instance arg should be of an outer class type
if (!instArg.getType().equals(ctrCls.getDeclaringClass().getType())) {
return false;
}
addArgDot(code, instArg);
// can't use another dot, force short name of class
return true;
}
private void inlineAnonymousConstructor(ICodeWriter code, ClassNode cls, ConstructorInsn insn) throws CodegenException {
cls.ensureProcessed();
if (this.mth.getParentClass() == cls) {
cls.remove(AType.ANONYMOUS_CLASS);
cls.remove(AFlag.DONT_GENERATE);
mth.getParentClass().getTopParentClass().add(AFlag.RESTART_CODEGEN);
throw new CodegenException("Anonymous inner class unlimited recursion detected."
+ " Convert class to inner: " + cls.getClassInfo().getFullName());
}
ArgType parent = cls.get(AType.ANONYMOUS_CLASS).getBaseType();
// hide empty anonymous constructors
for (MethodNode ctor : cls.getMethods()) {
if (ctor.contains(AFlag.ANONYMOUS_CONSTRUCTOR)
&& RegionUtils.isEmpty(ctor.getRegion())) {
ctor.add(AFlag.DONT_GENERATE);
}
}
code.attachDefinition(cls);
code.add("new ");
useClass(code, parent);
MethodNode callMth = mth.root().resolveMethod(insn.getCallMth());
if (callMth != null) {
// copy var names
List<RegisterArg> mthArgs = callMth.getArgRegs();
int argsCount = Math.min(insn.getArgsCount(), mthArgs.size());View on GitHub (pinned to e738a26571)
Solutions
- This exception is expected recovery — it should be caught by wrapCodeGen which retries. If it surfaces as a user-visible error, the restart path itself also failed (see error 69).
- If the restart also fails, report the class to jadx and use fallback mode.
- No action needed if the decompilation succeeds after the restart — this is by design.
Defensive patterns
Strategy: try-catch
Try / catch
// This exception is caught internally by wrapCodeGen which triggers a restart.
// If you see it surface, the restart also failed:
try {
codeGen.makeCode(cls);
} catch (JadxRuntimeException e) {
if (e.getMessage().equals("Code generation error after restart")) {
// The restart triggered by anonymous-class recursion also failed
Throwable cause = e.getCause();
logger.error("Anonymous class recursion recovery failed for: {}",
cls.getClassInfo().getFullName(), cause);
args.setDecompilationMode(DecompilationMode.FALLBACK);
} else {
throw e;
}
} Prevention
- Understand this exception is part of the recovery mechanism — it normally never surfaces.
- If it does surface, the restart retry also failed; examine the cause chain.
- Report the class with self-referential anonymous class patterns to jadx.
When it happens
Trigger: An anonymous class whose constructor triggers inlining of itself, creating a cycle. This can happen with self-referential anonymous class patterns in obfuscated or generated code. The exception forces a restart where the class is treated as a normal inner class instead.
Common situations: Obfuscated code with circular anonymous class references. Kotlin lambda or inner class patterns that reference their own enclosing type during construction. The error message names the class being converted.
Related errors
- Code generation error after restart
- Method generation error
- Failed to generate code for class: ${cls.getFullName()}
- Unexpected field type class:
- Can't decode value:
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/b6fcadf5dd7cabb9.
Report an issue: GitHub.