Android NDK项目中JNI包与cpp包的区别是什么?
Great question—this is such a common point of confusion when you’re dipping your toes into NDK development, so let’s break this down clearly, including addressing your assumption about file placement.
First: Is Your Assumption Correct?
Short answer: Physically, you could drop those files into either directory, but that’s a bad idea from a maintainability and code-standards perspective. The NDK build system (whether using Android.mk/Application.mk or CMake) is flexible enough to compile files from any path, but the two directories have distinct roles that you should follow to keep your project clean.
Core Differences Between JNI and C++ Directories
1. Primary Purpose & Responsibility
- JNI Directory (traditionally
jni/): This is the bridge layer between Java/Kotlin and your native code. Its sole job is handling cross-language interactions:- Defining JNI functions that map to
nativemethods in your Java classes (likeJava_com_example_myapp_MainActivity_stringFromJNI) - Converting between Java objects/types (e.g.,
jstringtostd::string) and native types - Calling Java methods or accessing Java fields from native code via the
JNIEnv*interface
Every file here should directly interact with the JNI API—this is not where you put your core business logic.
- Defining JNI functions that map to
- C++ Directory (often
cpp/, or a custom name likenative-core/): This is your native business logic layer. Here you’ll store pure C++ code that has nothing to do with Java interop:- Performance-sensitive algorithms (image processing, math computations)
- Wrappers for third-party native libraries
- Core application logic that’s better implemented in C++ for speed or code reuse
Code here uses standard C++ syntax and doesn’t depend on JNI headers or APIs—think of it as a standalone C++ library that just happens to be used by your Android app.
2. File Organization Best Practices
- Build config files like
Android.mk,Application.mk, orCMakeLists.txtare typically placed in or near the JNI directory (or the root of your native code tree) because they define how the NDK compiles the bridge and native code together. - Keep pure C++
.cpp/.hfiles strictly in the C++ directory—mixing them with JNI bridge code will make your project harder to debug, refactor, or reuse across other platforms. - Only JNI-specific
.cppfiles (the ones with theJava_*function signatures) belong in the JNI directory.
3. Dependencies & Compilation Logic
- JNI directory code requires linking against JNI headers and libraries (like
jni.hprovided by the NDK) to compile, since it directly interacts with the Java runtime. The output is a shared library (.so) that the Android Runtime (ART) can load and call from Java. - C++ directory code can be compiled as a static library (
.a) or shared library that’s consumed by the JNI bridge code. It doesn’t need any JNI dependencies—you can compile it using standard C++ toolchains, just like you would for a desktop C++ project.
4. Modern NDK Context
Quick side note: These days, Android Studio and the modern NDK favor using the cpp/ directory as the default for all native code, with CMake instead of Android.mk. Even so, the core separation still applies: you should split your JNI bridge code into a subdirectory (like cpp/jni/) and keep your pure C++ logic in another subdirectory (like cpp/core/) to maintain that clear responsibility line.
内容的提问来源于stack exchange,提问作者Ksenia

