SReverseby Simpa Labs

Dex analysis

JADX decompile errors and what they tell you

JADX reports a failed method instead of hiding it. That message describes the shape of the compiled code, and it tells you which part of the app was rewritten at build time.

The failure comment is a signal about the code

When JADX cannot recover Java for a method, it emits a notice in place of the body and, in most configurations, falls back to raw bytecode or omits the method. The notice rarely means the file is damaged. It means the bytecode in that method no longer matches the patterns the decompiler expects from source written by a person.

That happens for specific reasons. Obfuscators rewrite control flow with opaque predicates, flatten switch statements, and split a single method into fragments joined by gotos. Exception handlers get added where the original code had none. Structure is exactly what a decompiler needs to rebuild, so a method that has had its structure removed is the method that produces the notice.

Read the notice as a location. The classes around it are usually still readable, and their names, string constants and annotations survive obfuscation more often than method bodies do.

Reading the errors as a map of the build

Different causes produce failures in different places, and the distribution across the app tells you what was applied.

  • A wall of notices concentrated in a few classes points at a protector that rewrote those classes and left the rest of the app alone.
  • Notices spread evenly with short unexplained methods point at a mapper such as R8 or ProGuard, which removed structure through inlining and shrinking rather than by adding traps.
  • Interpreted or virtualised bytecode often appears as very large methods with a dispatch loop and almost no recoverable Java inside them.
  • Notices that appear only after a packer unpacks at run time should be suspected when the on-disk classes look small and the app loads additional dex at start-up.

A list of failed methods is also a shortlist of methods that matter. Build tooling does not usually spend effort on code that runs once at install, so heavy rewriting tends to land on the parts of the app that carry logic the vendor wanted to keep.

What to do instead of editing decompiler settings

Changing decompiler options can move the boundary between readable and unreadable output, and it is worth one attempt, but the settings are not the constraint. The information the decompiler needed is not present in the bytecode, so a better tool recovers a tidier rendering of the same incompleteness. Use the notice as a pointer and take a different view of that region.

  • Read the smali for the failed class. Smali is a direct transcription of the bytecode, so it always shows the instructions even when no Java can be recovered.
  • Compare against a second decompiler on the same method. Two tools that fail on the same method with different output tell you what is stable in the bytecode and what each one invented.
  • Look up the enclosing class in the strings table, because the routes, header names and JSON keys the method uses are addresses the code has to reference.
  • Record the method signature before you leave, so a later step can hook or breakpoint that exact method.

When the smali is unreadable too

If the smali shows only a small stub that calls into a shared library, the logic has left the dex layer. That arrangement is common in apps that keep their network and signing code in native code, and no amount of decompiler tuning will bring it back. The next view is the native library, which means symbol recovery, string recovery from read-only data, and tracing calls at the boundary between the managed and native layers. Native Android reverse engineering covers the tools for that stage.

Heavy obfuscation that resists static reading is the same problem described from the other direction in Android obfuscation reverse engineering, and protected builds are handled under protected APK reverse engineering.

What a reconstruction needs from this stage

The output of a dex study is a map rather than a listing. You want the endpoint definitions, the request builder, the signing routine and the token store, each with a name that can be referenced again. Failed methods matter because the signing routine is often one of them.

Establish which failed methods are on the request path before treating the decompile as a blocker. An app can fail to decompile a dozen classes and still expose every route, header and payload field as plain text. The reverse case is the one that needs more work: a route that is assembled at run time never appears as a literal, and the notice in that region is the first clue that the path is being computed rather than written down.

Reviewed 28 September 2026 · SReverse research desk

Start your full APK reconstruction

Send the full APK

Projects start at $120. Choose WhatsApp or email, then attach the APK in the app that opens. We reply within one hour with the next step and send the fixed quote after review.

Want us to contact you?