# How to Debug a Running Android Application with Reverse Engineering Tools

> Debug live Android apps by decompiling binaries with jadx or Fernflower and attaching Android Studio or jdb via JDWP to intercept runtime behavior.

- Repository: [Simone Avogadro/android-reverse-engineering-skill](https://github.com/SimoneAvogadro/android-reverse-engineering-skill)
- Tags: how-to-guide
- Published: 2026-04-17

---

**Debug any compiled Android binary by decompiling it with `jadx` or Fernflower, mapping the reconstructed sources to the live process via JDWP, and attaching Android Studio or `jdb` to intercept runtime behavior.**

The `android-reverse-engineering-skill` repository provides a complete, script-driven workflow for turning compiled Android binaries into debuggable source code. By combining static analysis with standard Android runtime tools, you can inspect variable states, network calls, and authentication flows in apps where you lack the original source.

---

## Prerequisites and Environment Setup

Before decompiling, verify that your environment contains Java 17+, `jadx`, and optional decompilers like Fernflower or Vineflower.

Run the dependency checker from the repository root:

```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/check-deps.sh

```

The script outputs machine-readable status lines such as `INSTALL_REQUIRED:jadx`. Install missing components automatically:

```bash
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/skills/android-reverse-engineering/scripts/install-dep.sh jadx
bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/install-dep.sh vineflower

```

**Why this matters:** Decompiling with the `--deobf` flag generates source files whose line numbers map directly to the original bytecode, enabling accurate breakpoint placement in Android Studio or `jdb`.

---

## Decompiling the Target Binary

First, pull the APK from the device to your workstation:

```bash
adb shell pm path com.example.app

# Output: package:/data/app/com.example.app-1/base.apk

adb pull /data/app/com.example.app-1/base.apk ./target.apk

```

Execute the decompilation wrapper to generate Java sources:

```bash

# Fast code-only extraction (no resources)

bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/decompile.sh --no-res target.apk

# For obfuscated apps, add deobfuscation

bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/decompile.sh --deobf target.apk

```

The script creates `target-decompiled/` containing `sources/` (Java) and `resources/` (manifest, layouts). When using `--deobf`, it also emits [`deobf-mapping.txt`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/deobf-mapping.txt), which you can import into Android Studio to restore original class names for debugging.

---

## Exploring Decompiled Code

Open the APK in `jadx-gui` for interactive navigation:

```bash
jadx-gui target.apk

```

**Capabilities for debugging preparation:**
- Search for class/method names or string constants to locate entry points.
- Toggle *Show line numbers* to align with the `sources/` tree produced by [`decompile.sh`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/decompile.sh).
- Trace the call hierarchy from UI event handlers (e.g., `LoginActivity.onCreate`) down to network clients.

### Locating Network Entry Points

Identify HTTP API calls using the extraction helper:

```bash

# Scan entire source tree

bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/find-api-calls.sh target-decompiled/sources/

# Focus on Retrofit annotations

bash plugins/android-reverse-engineering/skills/android-reverse-engineering/scripts/find-api-calls.sh target-decompiled/sources/ --retrofit

```

Output format shows exact file paths and line numbers:

```

=== Retrofit Annotations ===
src/main/java/com/example/api/ApiService.java:42:@GET("/v1/users")
src/main/java/com/example/api/ApiService.java:57:@POST("/v1/login")

```

Combine these results with the **call-flow analysis** reference documented in [`references/call-flow-analysis.md`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/references/call-flow-analysis.md) to map the complete path from UI components to the network layer.

---

## Attaching a Live Debugger

With decompiled sources and identified target methods, connect to the running process.

### Step 1: Launch and Prepare the Target

```bash

# Start the app if not running

adb shell am start -n com.example.app/.MainActivity

# Forward JDWP port for command-line debugging (optional)

adb forward tcp:8700 jdwp:<pid>

```

### Step 2: Load Sources in Android Studio

1. Open the generated `target-decompiled/sources/` directory (File → Open).
2. If you used `--deobf`, load the mapping: **File → Settings → Build, Execution, Deployment → Debugging → ProGuard mappings**, then select [`deobf-mapping.txt`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/deobf-mapping.txt).

### Step 3: Set Breakpoints and Attach

Place breakpoints on the methods identified earlier (e.g., `ApiService.login` at line 57).

**Android Studio method:**
- Run → Attach debugger to Android process → Select `com.example.app`.

**Command-line method:**

```bash
jdb -attach localhost:8700
> stop in com.example.api.ApiService.login
> run

```

### Step 4: Inspect Runtime State

Trigger the functionality in the app (e.g., tap the login button). The debugger halts at your breakpoint, allowing inspection of:
- Method parameters and local variables.
- Network request construction before it leaves the device.
- Authentication token generation logic.

You now possess both static visibility (decompiled sources) and dynamic visibility (live debugging) for an application without original source code.

---

## Summary

- **Prepare the environment** using [`check-deps.sh`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/check-deps.sh) and [`install-dep.sh`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/install-dep.sh) to ensure Java 17+ and decompilers are available.
- **Decompile** the target APK with [`decompile.sh`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/decompile.sh), using `--deobf` for obfuscated apps to preserve line number mappings.
- **Explore** the reconstructed sources in `jadx-gui` and identify network entry points via [`find-api-calls.sh`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/find-api-calls.sh).
- **Attach** Android Studio or `jdb` to the running process, loading deobfuscation mappings if available, to set breakpoints in decompiled methods.
- **Inspect** runtime variables and network flows at the exact points where the app constructs HTTP requests or handles sensitive data.

---

## Frequently Asked Questions

### How do I handle obfuscated apps when debugging?

Use the `--deobf` flag with [`decompile.sh`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/decompile.sh) to generate a [`deobf-mapping.txt`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/deobf-mapping.txt) file. Import this mapping into Android Studio under **Settings → Build, Execution, Deployment → Debugging → ProGuard mappings** to restore original class and method names, enabling accurate breakpoint placement in obfuscated code.

### Can I debug an app without pulling the APK first?

No, you must first extract the APK from the device using `adb shell pm path` and `adb pull` to obtain the binary. The decompilation process requires local access to the APK, XAPK, JAR, or AAR file to generate the source tree that you will attach to the debugger.

### What is the difference between jadx and Fernflower for debugging?

`jadx` produces more readable source code and includes a GUI (`jadx-gui`) for interactive exploration, making it ideal for initial analysis. Fernflower (or Vineflower) often yields more accurate line number mappings to the original bytecode, which can result in more precise breakpoint alignment when attaching a debugger to the running process. The [`decompile.sh`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/decompile.sh) script supports both engines via the `--engine` flag.

### How do I identify which methods to set breakpoints on?

Run [`find-api-calls.sh`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/find-api-calls.sh) against the decompiled sources to locate HTTP client calls (Retrofit, OkHttp, Volley) and hard-coded endpoints. Then consult the [`call-flow-analysis.md`](https://github.com/SimoneAvogadro/android-reverse-engineering-skill/blob/main/call-flow-analysis.md) reference to trace backward from these network methods to the UI entry points (Activities, Fragments, or ViewModels). Set breakpoints at the critical junctions where user input transforms into network requests.