Skip to main content
This page covers common problems NDK developers encounter and provides practical solutions. Many of these issues have straightforward fixes once you understand the underlying cause.

Build issues

This error occurs when the dynamic linker cannot find a required shared library.Common causes:
  • Library not packaged in the APK
  • ABI mismatch (e.g., loading arm64-v8a library on armeabi-v7a device)
  • Incorrect library name
  • Missing dependencies
Solutions:
  1. Verify the library exists in your APK:
  1. Check that you’re building for the correct ABIs:
  1. Ensure library name matches exactly:
  1. Check for missing dependencies:
The JNI method signature in your C/C++ code doesn’t match the Java declaration.Common causes:
  • Incorrect function name
  • Wrong package or class name in JNI function
  • Missing extern "C" in C++
  • Method not registered
Solutions:
  1. Generate the correct signature:
  1. Verify your JNI function name:
  1. Use extern "C" for C++ code:
  1. Alternative: Use dynamic registration:
Text relocations are not allowed on Android 6.0+ (API level 23) for security reasons.Error message:
Cause: Code was not compiled as position-independent code (PIC).Solution:Ensure you’re using -fPIC flag:
Or check your existing libraries:
If third-party libraries have text relocations, contact the vendor for an updated version.
The linker cannot find the implementation of a function or variable.Common causes:
  • Missing library in link command
  • Wrong link order
  • Symbol not exported
  • C++ name mangling issues
Solutions:
  1. Add the required library:
  1. Check symbol availability:
  1. Fix C++ name mangling:
  1. Check symbol visibility:
CMake can’t locate your NDK installation.Solutions:
  1. Set ANDROID_NDK environment variable:
  1. Specify in CMake command:
  1. Use Android Gradle Plugin (recommended):

Runtime issues

The most common native crash. Your code accessed invalid memory.Common causes:
  • Null pointer dereference
  • Use after free
  • Buffer overflow
  • Stack overflow
  • Invalid JNI reference
Debugging:
  1. Get the tombstone (see Understanding crashes)
  2. Use Address Sanitizer:
  1. Check JNI usage:
  1. Use Android Studio’s native debugger
Your code or a library called abort(), often due to assertion failures or critical errors.Common causes:
  • Failed assertion (assert() or CHECK())
  • Memory allocation failure
  • Fatal error in C++ standard library
  • Stack smashing detected
Debugging:Check the tombstone for the abort message:
Look at the stack trace to identify the failing assertion or error.
Native memory is not garbage collected. You must manually free allocated memory.Detection:Use Address Sanitizer with leak detection:
Common leak patterns:
  1. Missing free() or delete:
  1. JNI reference leaks:
You’ve created too many JNI local references without deleting them.Error:
Solution:
  1. Delete local references when done:
  1. Use PushLocalFrame/PopLocalFrame for bulk cleanup:
Multiple threads accessing shared data without synchronization.Detection:Use Thread Sanitizer:
Solutions:
  1. Use mutexes:
  1. Use atomic operations:
  1. Remember: Each thread needs its own JNIEnv*:

Platform-specific issues

The emulator and physical devices can have different characteristics.Common causes:
  • ABI mismatch (emulator is x86, device is ARM)
  • Uninitialized memory (different initial values)
  • Timing issues (emulator is slower)
  • Hardware features (NEON, SSE)
Solutions:
  1. Test on actual hardware early
  2. Use sanitizers to catch undefined behavior
  3. Check CPU features before using SIMD:
Android’s C library (bionic) and system behavior evolve over time.Solutions:
  1. Check API level at runtime:
  1. Review Android changes for NDK developers
  2. Test on multiple Android versions
Type size assumptions or ABI issues.Common causes:
  • Assuming int and pointers are same size
  • Assuming long is 32 bits
  • Structure packing differences
  • Inline assembly for wrong architecture
Solutions:See 32-bit ABI issues for detailed migration guide.Quick fixes:

Performance issues

Frequent JNI calls have overhead.Solutions:
  1. Batch operations:
  1. Cache JNI method IDs and field IDs:
  1. Use direct buffer access:
Native code uses too much memory.Solutions:
  1. Use tools to analyze:
  1. Reuse buffers:
  1. Free large allocations promptly
  2. Consider memory mapping for large files

Getting help

If you’re still stuck:
  1. Check tombstone files (see Understanding crashes)
  2. Enable detailed logging
  3. Search android-ndk GitHub issues
  4. Ask on android-ndk Google Group
  5. Review bionic documentation
Always include your NDK version, target API level, device/emulator info, and complete error messages when asking for help.