> For the complete documentation index, see [llms.txt](https://docs.hex-rays.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hex-rays.com/ida-9.5/core/decompiler/concepts/dalvik-decompiler.md).

# Dalvik decompiler

The Hex-Rays Decompiler supports Android bytecode (Dalvik/DEX). It turns DEX methods into Java-like source and can show whole classes, with their fields, methods, nested classes and annotations, in one view.

This page describes what is specific to Dalvik. The usual pseudocode actions (rename, set type, xrefs, jump, history, ...) work as described in [Decompiler Actions](/ida-9.5/core/decompiler/reference/decompiler-actions.md).

## Loading Dalvik files

Open an `.apk`, `.dex`, `.odex` or OAT/VDEX file. IDA creates a database with the DEX loader and the Dalvik processor module. The types (classes and method prototypes) come from the DEX files themselves, so you do not need to load any type libraries.

### Multidex applications

An APK can contain several DEX files (`classes.dex`, `classes2.dex`, ...). They are all loaded into one database, and the code in each file is linked to the code in the others as if it were one program:

* A call to a method defined in another DEX file goes to that method's body. Only methods that no loaded file defines go to the `IMPORTS` segment.
* A virtual call also has cross-references to the methods in subclasses that override it. This lets you find every method a call may reach. By default this is done only for the classes of the application. Set `OVERRIDE_XREFS_APP_ONLY = NO` in `dex.cfg` to also do it for calls into framework classes.
* `try`/`catch` blocks in `classes2.dex` and later files are recognized, both in the disassembly and in the decompiler.
* Field and method references in the decompiler resolve across files. A field renamed in one file shows its new name everywhere.

### Adding files to an existing database

Some applications load more code at run time, for example plugins or secondary DEX files stored as assets. You can add such files to a database that you have already analyzed, with the [Additional file with loader...](/ida-9.5/ida-actions/loadadditionalfile.md) action, under **File → Load file**.

1. Select a `.dex` or `.apk` file. You can also choose an ODEX file, or an OAT or VDEX file, but you cannot mix optimized and unoptimized DEX files in one database.
2. Confirm the warning. **Adding a file cannot be undone**, and the undo history is cleared. Make a backup copy of the database first.

The added files are linked with the files already in the database, just as if they had all been loaded together:

* Calls in the earlier files that went to `IMPORTS` now go to the method bodies in the new files. Their cross-references are updated.
* Classes that were only referenced before now get their full definition.
* Your edits are kept: renames and changes to the types of classes that the new files do not affect.
* If a new file defines a class that is already in the database, the earlier definition is used, as on a Java class path. The Output window lists such classes.
* The class tree is rebuilt, and the class views are closed. Decompiled methods are decompiled again when you next view them, because their calls may now reach new code.

A file that is already in the database is refused. So are additions to a database created by an older version of IDA: create a new database from the original file first.

The same operation is available to scripts as `ida_loader.load_additional_file(path)`.

## The Java-like output

The decompiler prints Java syntax:

* `java.lang.` is omitted. Other class names are fully qualified with dots, or shortened in the class view when the name is unambiguous. Arrays print as `int[]` and `String[][]`.
* `this`, `super(...)`, `new X(...)`, `instanceof`, casts, `X.class` literals and static fields (`Class.field`) are all supported.
* Constructors print with the class name, and the static initializer prints as `static { ... }`.
* String concatenation is rebuilt from `StringBuilder` chains: `"n=" + count`.
* Array creation and initializers come out as `new int[] { 1, 2, 3 }`.
* `synchronized` blocks are rebuilt, nested ones included.
* `try`/`catch`/`finally` and multi-catch are rebuilt. Some cases are only approximated; see [Limitations](#limitations).
* `switch` on integers is supported.
* Parameter names come from the debug info when the DEX file has it. Otherwise parameters are named `p0`, `p1`, .... A `long` or `double` parameter takes two slots, so the next one skips a number (`long p3, boolean p5`).
* Every local variable declaration ends with a comment naming its Dalvik register, for example `int i; // V1`.

Example:

```java
public void nestedSyncBlocks()
{
  Object lockA; // V0
  Object lockB; // V4

  lockA = this.lockA;
  synchronized ( lockA )
  {
    System.out.println(Thread.currentThread().getName() + ": holding lockA");
    lockB = this.lockB;
    synchronized ( lockB )
    { ... }
    return;
  }
}
```

There are two ways to look at decompiled code:

* **Pseudocode window (**<kbd>**F5**</kbd>**).** It shows a single method. The method name is qualified with its class, and types are fully qualified.
* **Class view.** It shows whole classes, as described below. This is the recommended way to read Dalvik code.

## Class tree

The class tree is a browser of all classes in the database. Its window is titled **Dalvik classes**.

The first time a new Dalvik database is opened, the class tree opens automatically, docked where the Functions window was. It replaces the Functions window for Dalvik databases. To open it again later, use the [Class tree](/ida-9.5/ida-actions/dalvik_ui_show_class_tree.md) action under **View → Open subviews**.

![Class tree](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-5aacca7a9483baa0e5446bc68c7bb69223d8f5a2%2Fdalvik_class_tree.png?alt=media)

What it shows:

* **Folders** are packages and classes. Nested classes are subfolders of their outer class. A chain of packages that each have only one child is merged into one folder, for example `com.google.android`.
* **Methods** are shown as `name(Type1, Type2)` with short type names. The return type is omitted, except where two methods differ only in their return type (bridge methods), which get `: RetType` appended.
* **Fields** are shown as `name : Type`.
* The **Info** column shows the size of each method, in 16-bit code units.
* Only classes defined in the database are listed. Framework classes that are only referenced are not.

Using the tree:

| Action                                                                             | Result                                                                             |
| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| <kbd>Enter</kbd> or double-click on a class                                        | Opens the class in a class view, at its declaration                                |
| <kbd>Enter</kbd> or double-click on a method or field                              | Opens its class in a class view, at the member                                     |
| <kbd>Enter</kbd> or double-click on a package                                      | Expands or collapses it                                                            |
| <kbd>Shift</kbd> + <kbd>Enter</kbd> or <kbd>Shift</kbd> + double-click on a method | Opens the method in a pseudocode window instead                                    |
| <kbd>Ctrl</kbd> + <kbd>Enter</kbd> or <kbd>Ctrl</kbd> + double-click               | Same as above, but always in a new window                                          |
| [**Open class**](/ida-9.5/ida-actions/dalvik_ui_open_class.md) (context menu)      | Opens the selected class, or the class of the selected member, in a new class view |

Like other folder views in IDA, the tree supports filtering, sorting, creating and renaming folders, and moving items by drag-and-drop or by cut and paste. The layout you create is saved in the database. New members are placed into their natural package and class folder, and items you moved stay where you put them.

On large databases, a wait box is shown while the tree is built. It can be cancelled. The items not placed yet will be placed the next time the tree is opened.

## Class view

The class view shows decompiled Java classes as source text. Its windows are titled **Classes-A**, **Classes-B**, and so on.

![Class view](https://492083732-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFP6ibt8r6WPBHTqekG9u%2Fuploads%2Fgit-blob-41ce7db221bacf5c2e2ae9573ce9baf71a6e81e5%2Fdalvik_class_view.png?alt=media)

You can open it in several ways:

* From the class tree or from search results, as described above. The view then shows that one class, together with its nested classes.
* With the [Classes](/ida-9.5/ida-actions/dalvik_ui_open_class_view.md) action under **View → Open subviews** (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>F6</kbd>). This opens a new view of all classes. When used from the disassembly, the view starts at the member under the cursor.
* With <kbd>Tab</kbd> in the disassembly. This goes to the corresponding method and statement in the class view. <kbd>Tab</kbd> in the class view goes back to the disassembly.

A view that shows one class follows your navigation. When you jump to another class, the view switches to that class.

### What a class looks like

For each top-level class the view shows:

* `// source: Foo.java`, from the source file name recorded in the DEX file.
* The `package` line.
* Class annotations, such as `@Retention(RUNTIME)`. Annotations used internally by the compiler (`dalvik.annotation.*` and `kotlin.Metadata`) are not printed. Their information is used instead: generic signatures, `throws` clauses, inner class names, and field names.
* The class declaration: its modifiers, `class`, `interface`, `enum` or `@interface`, generic type parameters, and `extends` and `implements`.
* Fields, with their annotations, modifiers and constant initial values (`public static final int MAX = 42;`).
* Methods. Each method is preceded by a `//----- (address) ---` line and shows its full decompiled body. Abstract, native and interface methods are shown as declarations with a `throws` clause, parameter names and generics.
* Nested classes, inside their outer class.
* Anonymous classes, as `new Super() { ... }`, with a comment giving the DEX class name and the method that creates them.

Compiler-generated code is hidden where Java source would not contain it:

* default constructors;
* the constructors of anonymous classes;
* the `values()`, `valueOf()`, `$VALUES` and `<clinit>` members of enums.

Enums are rebuilt from their static initializer. The constants are listed in declaration order, together with constant bodies:

```java
public enum Direction
{
  NORTH, SOUTH, EAST, WEST;
}
```

If the static initializer cannot be fully analyzed, the decompiler issues the warning *"could not fully analyze enum ; constant order or bodies may be incomplete"* and shows the `static { ... }` block so that you can inspect it.

Decompiler warnings for a method appear as comments after its body. If a method cannot be decompiled, its body is replaced by an `#error` line.

### Working in the class view

Methods are decompiled on demand, when they first appear on the screen. Scrolling through a large class therefore does not decompile the whole program up front.

Method bodies in the class view support the usual pseudocode actions:

* jump to a callee or field (<kbd>Enter</kbd> or double-click), cross-references, and navigation history;
* rename methods, fields and local variables;
* set the type of local variables and arguments, and the prototype of a method. Types use Java syntax. A field can also be retyped, but its new type must have the same size (32 or 64 bits);
* **Generate pseudocode** (<kbd>F5</kbd>) in the class view decompiles again all methods of the current class, including its nested classes.

Renaming or retyping anything automatically refreshes the affected methods in all open class views.

The classes of the application are also types in the **Local Types** view, each class a structure with its fields. You can edit these types there: rename a class or a field, or change a field's type. The disassembly is updated at once. A renamed class is also updated at once in the decompiler output. Other changes show in the decompiler output after a refresh: press <kbd>F5</kbd> in the class view to decompile again the class under the cursor, including its nested classes, or press <kbd>F5</kbd> in the pseudocode window.

Some actions are not supported in the class view yet. You get one of these messages:

* *"Sorry, helper calls cannot be retyped in the class view yet"*
* *"Sorry, helper calls cannot be renamed in the class view yet"*
* *"Sorry, method calls and globals cannot be retyped in the class view yet"*

Use the pseudocode window (<kbd>Shift</kbd> + <kbd>Enter</kbd> in the class tree) for these cases.

The desktop saves the position and the displayed class of each open class view.

## Searching classes and members

**Search classes and members...** (<kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>F</kbd>) is available in the context menus of the class tree, the class views and the search result windows. It searches classes, inner classes, methods, fields and packages by name, with options for case, whole words and regular expressions. See [Search classes and members](/ida-9.5/ida-actions/dalvik_ui_search.md) for the dialog and the results window.

## Exporting the source

**File → Produce file → Create C file...** (<kbd>Ctrl</kbd> + <kbd>F5</kbd>) and batch decompilation write the whole program in class form. The classes are grouped by package. Each package group starts with its `package` line and the `import` lines its classes need. The output does not contain the C boilerplate (type declarations, `#include` lines) that other processors get.

## ODEX files

In optimized DEX (ODEX) files, some instructions are "quickened": they refer to fields by memory offset and to methods by vtable slot instead of by name. The decompiler converts them back to field and method names when it knows the class layout. When it does not, the instruction is shown as a helper call, and the name is never guessed:

| Helper                                               | Meaning                     |
| ---------------------------------------------------- | --------------------------- |
| `__iget_quick__(obj, offset)`, `__iput_quick__(...)` | Field access by offset      |
| `__invoke_vtable__(receiver, slot, ...)`             | Virtual call by vtable slot |
| `__execute_inline__(index, ...)`                     | Inlined framework method    |

Most of these unresolved calls are to Android framework classes, because the framework is not loaded. You can resolve the calls to one class yourself: name the slots and members in its `<class>_vtbl` local type and in its class structure.

Methods in OAT/VDEX files that contain ART-quickened instructions are not decompiled. Decompilation fails instead of producing wrong code.

## Limitations

### Language features

* **Lambdas** appear as the compiler-generated methods (`lambda$0`, `setupMap$lambda$6`) or classes, not as `->` expressions. Methods that use `invoke-custom`, `invoke-polymorphic` or method handle constants cannot be decompiled.
* **Switch on an enum** appears as comparisons of `ordinal()` against integers. **Switch on a string** appears in the two-step form the compiler generates (a `hashCode()` switch followed by `equals()` tests).
* **Variable arguments** are passed as an explicit array.
* **Generics** are shown in declarations only, and they do not affect types. Method bodies use raw types (`Map`, `new ArrayList()`).
* **Compiler desugaring** by javac, D8 and R8 is mostly not undone: `access$NNN` accessors, `$SwitchMap` tables and try-with-resources backports are all visible.
* **Kotlin** code is shown as its bytecode does it. Calls such as `Intrinsics.checkNotNullParameter(...)` remain, coroutines appear as state machines, and companion objects appear as separate classes. Kotlin nullability, `suspend` and data classes are not reflected.
* **Obfuscated** names are kept as they are in the DEX file. Names that are not valid Java identifiers are quoted with backticks.
* **Field names** may be taken from serializer or Kotlin annotations, so a field may show a different name than in the DEX file. Such a field carries a `// was b` comment, and the disassembly and the Names window keep the DEX name.
* **Local variable names** usually differ from the source: locals are named after the value they hold (a call or field), or `vN`.

### Exception handling (beta)

Rebuilding `try`/`catch`/`finally` is the least mature part of the Dalvik decompiler. Check the disassembly when something looks wrong. [Dalvik exception handler](/ida-9.5/core/decompiler/concepts/dalvik-exception-handler.md) explains how these constructs are encoded and recognized. Known issues:

1. A `catch` or `finally` block may use the value a variable had before the `try`. A typical symptom is an empty `finally {}` with the cleanup code on the normal path, together with the warning "conditional instruction was optimized away".
2. The code of a `finally` block may appear twice: inside a `catch` and again in the `finally`.
3. Statements right before or after a `try` may end up in the wrong block. This happens most often with try-with-resources, with `break` or `return` inside `try`/`finally` in a loop, and with consecutive `try` blocks that have identical handlers (these may be shown nested).
4. A `goto` across a `try`/`finally` boundary is ambiguous.
5. Helper calls that are not valid Java may remain: `__eh_try()`, `__eh_catch()`, `__eh_catch_type(X)`, `__catch_exception__()`.
6. When a register is reused for values of different types, you may see strange casts, assignments to `this`, `throw 0;` instead of `throw null;`, or warnings that a variable is possibly undefined.

### Other

* Helper calls such as `__monitor_enter__`, `__fill_array_data__` or `__check_cast__` appear when an instruction could not be converted to Java syntax.
* Types that cannot be resolved are printed as `?`, for example `catch ( ? e )`.
* A malformed switch table is dropped, and execution falls through to the default case.
* Class tree members cannot be renamed from the tree. Rename them in the class view.

## Reporting problems

When you report a wrong decompilation, please attach the database (or the APK/DEX file) and give the class and method name. If you have the original Java or Kotlin source, please attach it too.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.hex-rays.com/ida-9.5/core/decompiler/concepts/dalvik-decompiler.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
