Android Studio displays the "Prompt Dual (Java + Native) (15971)(disassembly)" error when the debugger fails to attach properly to native C++ threads. This occurs because the IDE cannot synchronize the Java and Native debug sessions, forcing it into a disassembly view instead of showing source code. Resolving this requires verifying your CMakeLists.txt configuration, ensuring proper ABI filtering, and restarting the debug daemon to clear stale connection states.
Understanding the Debug Attachment Failure
When you attempt to debug an Android application that uses JNI (Java Native Interface), Android Studio launches two distinct debuggers: one for the Java/Kotlin layer and another for the native C++ layer using LLDB. The error message indicates that these two processes are failing to handshake correctly. Instead of stepping through your C++ source files, the debugger falls back to viewing raw machine instructions, which is useless for standard development workflows. This specific failure mode often happens during the initial launch phase. The system detects that the native library has loaded, but the symbol table required to map memory addresses to variable names and line numbers is either missing, corrupted, or mismatched between the build output and the running process. If you have recently refactored your project structure or changed compiler flags, the cached debug information may no longer align with the compiled binary.Verifying CMake Configuration
The most common cause lies in how the native libraries are defined in yourCMakeLists.txt file. You must ensure that the add_library command correctly specifies the type of library you are building. For debugging to work seamlessly, shared libraries (SHARED) are generally preferred over static libraries (STATIC) because they can be loaded and unloaded dynamically by the Android runtime.
Check your build script for the following pattern:
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
If you are using static libraries, ensure they are linked correctly via target_link_libraries. However, switching to shared libraries is the standard recommendation for resolving attachment issues. Additionally, verify that you are not stripping symbols from your release builds if you intend to debug those configurations, although this is rare in development environments.
Configuring ABI Filters Correctly
Android devices support multiple CPU architectures, includingarmeabi-v7a, arm64-v8a, x86, and x86_64. If your APK contains binaries for architectures that do not match the device you are testing on, or if the ABI filters are misconfigured in your build.gradle file, the debugger may fail to locate the correct native thread.
Open your module-level build.gradle file and inspect the ndk block. Ensure that the abiFilters list includes only the architectures relevant to your target device. Over-filtering can result in an APK that lacks the necessary native code for the emulator or physical device, causing the debugger to hang or crash immediately upon launch.
android {
defaultConfig {
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
}
}
If you are developing for emulators, remember that x86_64 emulators require the corresponding x86_64 native libraries. Mixing ARM libraries on an x86 emulator will lead to immediate crashes or silent failures in the debugger attachment process.
Restarting the Debug Daemon
Sometimes, the issue is not with the code but with the state of the Android Debug Bridge (ADB) or the LLDB server itself. Stale connections can persist even after you stop a run configuration. To resolve this, open the Terminal window in Android Studio and execute the following commands to kill any hanging ADB servers and restart the service:adb kill-server
adb start-server
After restarting the server, clean your project by navigating to Build > Clean Project and then Build > Rebuild Project. This ensures that all intermediate build artifacts are removed and regenerated. When you rebuild, Android Studio will recompile the native code with fresh debug symbols, which should resolve any symbol table mismatches.
Checking GDB Server Settings
For projects using older NDK versions or specific toolchains, the GDB server settings might interfere with LLDB. While modern Android Studio defaults to LLDB, legacy configurations may still reference GDB. Navigate to Run > Edit Configurations and check the GDB Server tab if available. Ensure that the path to the GDB server executable is correct, though it is recommended to migrate to LLDB entirely for better performance and stability. If you are using third-party libraries that include pre-compiled native binaries, ensure those libraries were built with debug symbols enabled. Pre-compiled binaries without debug info will prevent the IDE from displaying source code, leading to the disassembly view regardless of your local configuration.Verifying Device Compatibility
Ensure that your physical device or emulator has USB debugging enabled and that the developer options are active. On physical devices, confirm that the USB connection mode is set to file transfer or MTP, as some PTP modes can interfere with high-bandwidth debug data streams. For emulators, verify that the hardware acceleration (HAXM or Hyper-V) is installed and functioning correctly, as poor emulation performance can cause timeout errors during the debugger attachment phase. If you continue to experience issues, consider checking the logcat output for errors related todebuggerd or lldb. These logs often provide specific error codes that can pinpoint whether the issue is permission-based, architecture-based, or related to missing dependencies.
Frequently Asked Questions
Why does my debugger show assembly code instead of C++?
This happens when the debugger cannot find the debug symbols (DWARF info) associated with the compiled binary. It usually means the build was done in Release mode, which strips symbols, or the APK installed on the device does not match the version currently in your IDE.
How do I fix "Unable to attach loader" errors?
This error typically indicates that the LLDB server cannot load the native library into memory. Verify that the library name in your JNI code matches the filename in your System.loadLibrary call exactly, and ensure the library is present in the APK's lib/ directory for the target ABI.
Can I debug C++ code on an iOS simulator?
No, C++ debugging via JNI is specific to the Android platform. iOS uses different mechanisms like Objective-C or Swift, and while C++ is supported, the toolchain and integration within Xcode differ significantly from Android Studio's LLDB setup.
What should I do if the debugger crashes immediately?
If the debugger crashes, check the logcat for fatal signals like SIGSEGV or SIGABRT. This often points to a bug in the native code itself, such as a null pointer dereference or stack overflow, rather than a configuration issue with Android Studio.
Does enabling ProGuard affect C++ debugging?
ProGuard primarily affects Java and Kotlin code. However, if you use R8 or ProGuard rules that strip native methods or rename them unexpectedly, it can break the JNI bridge. Ensure your proguard-rules.pro file keeps all native method signatures intact using -keepclasseswithmembers.