Build issues
UnsatisfiedLinkError: dlopen failed: library not found
UnsatisfiedLinkError: dlopen failed: library not found
- Library not packaged in the APK
- ABI mismatch (e.g., loading arm64-v8a library on armeabi-v7a device)
- Incorrect library name
- Missing dependencies
- Verify the library exists in your APK:
- Check that you’re building for the correct ABIs:
- Ensure library name matches exactly:
- Check for missing dependencies:
UnsatisfiedLinkError: No implementation found for native method
UnsatisfiedLinkError: No implementation found for native method
- Incorrect function name
- Wrong package or class name in JNI function
- Missing
extern "C"in C++ - Method not registered
- Generate the correct signature:
- Verify your JNI function name:
- Use
extern "C"for C++ code:
- Alternative: Use dynamic registration:
Build fails with 'text relocations' error
Build fails with 'text relocations' error
-fPIC flag:Undefined reference to symbol
Undefined reference to symbol
- Missing library in link command
- Wrong link order
- Symbol not exported
- C++ name mangling issues
- Add the required library:
- Check symbol availability:
- Fix C++ name mangling:
- Check symbol visibility:
CMake cannot find Android NDK
CMake cannot find Android NDK
- Set
ANDROID_NDKenvironment variable:
- Specify in CMake command:
- Use Android Gradle Plugin (recommended):
Runtime issues
Crashes with SIGSEGV (segmentation fault)
Crashes with SIGSEGV (segmentation fault)
- Null pointer dereference
- Use after free
- Buffer overflow
- Stack overflow
- Invalid JNI reference
- Get the tombstone (see Understanding crashes)
- Use Address Sanitizer:
- Check JNI usage:
- Use Android Studio’s native debugger
Crashes with SIGABRT (abort)
Crashes with SIGABRT (abort)
abort(), often due to assertion failures or critical errors.Common causes:- Failed assertion (
assert()orCHECK()) - Memory allocation failure
- Fatal error in C++ standard library
- Stack smashing detected
Memory leaks in native code
Memory leaks in native code
- Missing
free()ordelete:
- JNI reference leaks:
JNI local reference table overflow
JNI local reference table overflow
- Delete local references when done:
- Use
PushLocalFrame/PopLocalFramefor bulk cleanup:
Threading issues and race conditions
Threading issues and race conditions
- Use mutexes:
- Use atomic operations:
- Remember: Each thread needs its own
JNIEnv*:
Platform-specific issues
Works on emulator but crashes on device
Works on emulator but crashes on device
- ABI mismatch (emulator is x86, device is ARM)
- Uninitialized memory (different initial values)
- Timing issues (emulator is slower)
- Hardware features (NEON, SSE)
- Test on actual hardware early
- Use sanitizers to catch undefined behavior
- Check CPU features before using SIMD:
Different behavior on different Android versions
Different behavior on different Android versions
- Check API level at runtime:
- Review Android changes for NDK developers
- Test on multiple Android versions
App works on 32-bit but fails on 64-bit
App works on 32-bit but fails on 64-bit
- Assuming
intand pointers are same size - Assuming
longis 32 bits - Structure packing differences
- Inline assembly for wrong architecture
Performance issues
Slow JNI calls
Slow JNI calls
- Batch operations:
- Cache JNI method IDs and field IDs:
- Use direct buffer access:
Excessive memory usage
Excessive memory usage
- Use tools to analyze:
- Reuse buffers:
- Free large allocations promptly
- Consider memory mapping for large files
Getting help
If you’re still stuck:- Check tombstone files (see Understanding crashes)
- Enable detailed logging
- Search android-ndk GitHub issues
- Ask on android-ndk Google Group
- Review bionic documentation