Android Studio provides a debugger that lets you do the following and more:
This page includes instructions for basic debugger operations. For more documentation, also see the IntelliJ IDEA debugging docs.
Before you can begin debugging, do the following:
Use a build variant that
includes debuggable true
(isDebuggable = true in Kotlin scripts) in the build configuration.
Usually, you can select the default "debug" variant that's included in every Android Studio
project, even though it's not visible in the build.gradle file. However, if you
define new build types that should be debuggable, you must add debuggable true
to the build type:
android { buildTypes { customDebugType { debuggable true ... } } }
android { buildTypes { create("customDebugType") { isDebuggable = true ... } } }
This property also applies to modules with C/C++ code.
Note: The
jniDebuggable property is no longer used.
If your app depends on a library module that you also want to debug, that library must also
be packaged with debuggable true so it retains its debug symbols.
To ensure that the debuggable variants of your app project receive the debuggable variant of
a library module, publish non-default versions of your library.
You can start a debugging session as follows:
If you don't have any devices configured, then you need to either connect a device via USB, connect a device via Wi-Fi, or create an AVD to use the Android Emulator.
.
If your app is already running on the device, a dialog is displayed asking if you want to switch from Run to Debug. The device will need to restart in order to begin debugging. To keep the same instance of the app running, click Cancel Debug and instead attach the debugger to a running app. Otherwise, Android Studio builds an APK, signs it with a debug key, installs it on your selected device, and runs it.
If you add C and C++ code to your project, Android Studio also runs the LLDB debugger in the Debug window to debug your native code.
in the tool window bar.If your app is already running on your device, you can start debugging without restarting your app as follows:
.
The Debug window appears.
The Processes tab in the Device Explorer (View > Tool Windows > Device Explorer)
also has a list of debuggable processes. From there you can select a process and perform a kill
,
force-stop
,
or attach the debugger to a given process
.
The debug window is divided into
Note: The Android Studio debugger and garbage collector are
loosely integrated. The Android virtual machine guarantees that any object
the debugger is aware of is not garbage collected until after the debugger
disconnects. This can result in a buildup of objects while the
debugger is connected. For example, if the debugger sees a running thread,
the associated Thread
object is not garbage collected until the debugger disconnects, even if the thread has terminated.
Because different debugger tools are required to debug Java/Kotlin code and C/C++ code, the Android Studio debugger lets you select which debugger type to use. By default, Android Studio decides which debugger to use based on which languages it detects in your project using the Detect Automatically debugger type.
To manually select the debugger in the debug configuration, click Run > Edit Configurations. You can also select the debugger in the dialog that appears when you click Run > Attach debugger to Android process.
The debug types available include the following:
Native debugging only works on devices that meet the following requirements:
The device supports run-as.
To check whether the device supports run-as, run the following command on
the ADB shell that is connected to your device:
run-as your-package-name pwd
Replace your-package-name with your app's package name. If the
device supports run-as, the command should return without any errors.
The device has ptrace enabled.
To check whether ptrace is enabled, run the following command on the ADB
shell that is connected to your device:
sysctl kernel.yama.ptrace_scope
If ptrace is enabled, the command will print the value 0 or an
an unknown key error. If ptrace is not enabled, it will print a
value other than 0.
In figure 2, notice the two tabs to the right of the Debug window title. Because the app has both Java and C++ code, one tab is for debugging the native code and the other for debugging Java code, as indicated by -java.
Note: While debugging native code that is optimized by the
compiler, you may get the following warning message:This function was
compiled with optimizations enabled. Some debugger features may not be
available. When using optimization flags, the compiler makes changes to your
compiled code to make it run more efficiently. This can cause the debugger to
report unexpected or incorrect information because it’s difficult for the
debugger to map the optimized compiled code back to the original source code.
For this reason, you should disable compiler optimizations while debugging
your native code.
The system log shows system messages while you debug your app. These messages include information from apps running on the device. If you want to use the system log to debug your app, make sure your code writes log messages and prints the stack trace for exceptions while your app is in the development phase.
To write log messages in your code, use the
Log class. Log messages help
you understand the execution flow by collecting the system debug output while
you interact with your app. Log messages can also tell you what part of your
app failed. For more information about logging, see
Write and view logs with Logcat.
The following example shows how you might add log messages to determine whether previous state information is available when your activity starts:
import android.util.Log ... class MyActivity : Activity() { ... override fun onCreate(savedInstanceState: Bundle?) { ... if (savedInstanceState != null) { Log.d(TAG, "onCreate() Restoring previous state") /* restore state */ } else { Log.d(TAG, "onCreate() No saved state available") /* initialize app */ } ... } ... companion object { private val TAG: String = MyActivity::class.java.simpleName ... } }
import android.util.Log; ... public class MyActivity extends Activity { private static final String TAG = MyActivity.class.getSimpleName(); ... @Override public void onCreate(Bundle savedInstanceState) { ... if (savedInstanceState != null) { Log.d(TAG, "onCreate() Restoring previous state"); /* restore state */ } else { Log.d(TAG, "onCreate() No saved state available"); /* initialize app */ } ... } }
During development, your code can also catch exceptions and write the stack trace to the system log:
fun someOtherMethod() { try { ... } catch (e : SomeException) { Log.d(TAG, "someOtherMethod()", e) } }
void someOtherMethod() { try { ... } catch (SomeException e) { Log.d(TAG, "someOtherMethod()", e); } }
Note: Remove debug log messages and stack trace print calls from
your code when you are ready to publish your app. To do so, set a DEBUG
flag and place debug log messages inside conditional statements.
You can view and filter debug and other system messages in the Logcat window, as shown
in figure 4. For example, you can see messages when garbage collection occurs or messages that
you add to your app with the
Log class.
To use Logcat, start debugging and select the Logcat tab.
For a description of Logcat and its filtering options, see Write and view logs with Logcat.
Android Studio supports breakpoints that trigger different debugging actions. There are a several types types of breakpoint:
You can set conditional breakpoints that will only suspend execution if specific conditions are met. You can also set logging breakpoints that write to Logcat without suspending execution. This can help avoid littering your code with log statements.
To add a line breakpoint, proceed as follows:
. Otherwise, to start debugging, click Debug
.
A red dot appears next to the line when you set a breakpoint, as shown in figure 5.
When your code execution reaches the breakpoint, Android Studio pauses execution of your app.
To identify the state of the app, use the tools in the Debugger tab:
To examine the object tree for a variable, expand it in the Variables view. If
the Variables view is not visible, click Layout Settings
and ensure that
variables is checked.
To advance to the next line in the code without entering a method, click Step
Over
.
To advance to the first line inside a method call, click Step
Into
.
To advance to the next line outside the current method, click Step
Out
.
To continue running the app normally, click Resume Program
.
If your project uses any native code, by default the Detect Automatically debug type attaches both the Java debugger and LLDB to your app as two separate processes. You can switch between inspecting Java and C/C++ breakpoints without restarting your app or changing settings.
Note: For Android Studio to detect breakpoints in your C or C++ code, you need to use a debug type that supports LLDB, such as Detect Automatically, Native, or Dual. You can change the debug type Android Studio uses by editing your debug configuration. To learn more about the different debug types, read the section about using other debug types.
When Android Studio deploys your app to your target device, the Debug window opens with a tab or debug session view for each debugger process, as shown in figure 6.
Although the Threads pane is not available in the LLDB session view, you can access your app processes using the list in the Frames pane. Learn more about these panes in the sections about how to debug window frames and inspect variables.
Note: While inspecting a breakpoint in your native code, the Android system suspends the virtual machine that runs your app’s Java bytecode. This means that you are unable to interact with the Java debugger or retrieve any state information from your Java debugger session while inspecting a breakpoint in your native code.
While debugging C/C++ code, you can also set special types of breakpoints, called watchpoints, that can suspend your app process when your app interacts with a particular block of memory. To learn more, read the section about how to add watchpoints.
To view all the breakpoints and configure breakpoint settings, click
View Breakpoints
in the
Debug window. The Breakpoints window appears,
as shown in figure 7.
The Breakpoints window lets you enable or disable each breakpoint from the list in the pane. If a breakpoint is disabled, Android Studio doesn't pause your app when it hits that breakpoint.
Select a breakpoint from the list to configure its settings. You can configure a breakpoint to be disabled at first and have the system enable it after a different breakpoint is hit. You can also configure whether a breakpoint should be disabled after it is hit. To set a breakpoint for any exception, select Exception Breakpoints in the list of breakpoints.
To temporarily disable all breakpoints, click Mute Breakpoints
in the
Debug window. Click again to re-enable.
In the Debugger window, the Frames pane lets you inspect the stack frame that caused the current breakpoint to be hit. This enables you to navigate and examine the stack frame and also inspect the list of threads in your Android app.
To select a thread, use the thread selector menu and view its stack frame. Click the elements in the frame to open the source in the editor. You can also customize the thread presentation and export the stack frame as discussed in the Examine Frames guide.
In the Debugger window, the Variables pane lets you inspect variables when the system stops your app on a breakpoint and you select a frame from the Frames pane. The Variables pane also lets you evaluate ad hoc expressions using static methods and/or variables available within the selected frame.
To add an expression to the object tree (while the application is being debugged):
Alternatively, if the object tree contains the expression you want to watch, you can drag it to the top of the tree to add it as a watched expression.
Watched expressions will update when breakpoints are hit or you step through your code.
Evaluated expressions will remain displayed at the top of the object tree until you manually evaluate another expression or step through your code.
To remove a watched expression from the object tree, right-click the expression and then click Remove Watch.
While debugging C/C++ code, you can set special types of breakpoints, called watchpoints, that can suspend your app process when your app interacts with a particular block of memory. For example, if you set two pointers to a block of memory and assign a watchpoint to it, using either pointer to access that block of memory triggers the watchpoint.
In Android Studio, you can create a watchpoint during runtime by selecting a specific variable, but LLDB assigns the watchpoint to only the block of memory the system allocates to that variable, not the variable itself. This is different from adding a variable to the Watches pane, which enables you to observe the value of a variable but doesn’t let you suspend your app process when the system reads or changes its value in memory.
Note: When your app process exits a function and the system deallocates its local variables from memory, you need to reassign any watchpoints you created for those variables.
To set a watchpoint, you must meet the following requirements:
__attribute__((aligned(num_bytes))) in the
variable deceleration, as shown below:
// For a 64-bit ARM processor int my_counter __attribute__((aligned(8)));
Note: When debugging your app with 32-bit ARM ABIs, adding a watchpoint or hovering over variables inside the code to investigate their values may cause a crash. As a workaround, debug using 64-bit ARM, x86, or x86_64 binaries. This issue will be fixed in an upcoming Android Studio release.
If you meet the requirements, you can add a watchpoint as follows:
Right-click a variable that occupies the block of memory you want to track and select Add Watchpoint.
A dialog to configure your watchpoint appears, as shown in figure 9.
Configure your watchpoint with the following options:
To view all your watchpoints and configure watchpoint settings, click View Breakpoints
in the Debug window. The
Breakpoints dialog appears, as shown in figure 10.
After you add your watchpoint, click Resume Program
in the Debug window to resume your app
process. By default, if your app tries to access a block of memory that you
have set a watchpoint to, the Android system suspends your app process and a
watchpoint icon
appears next to the line of code that your app
executed last, as shown in figure 11.
In debug mode, you can view resource values and select a different display format for variables in your Java or Kotlin code. With the Variables tab displayed and a frame selected, do the following:
The available formats depend on the data type of the resource you selected. You might see one or more of the following options:
MeasureSpec.Integer.To create a custom format, do the following:
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2026-10-28 UTC.