干货|JNI实现机制
methodID_toString = NULL;
}
//隐式注册
extern "C" JNIEXPORT jstring JNICALL
Java_com_mob_test_jni_testjni_JNIMethods_stringFromJNI(JNIEnv *env, jobject jobj) {
LOGD("test-jni.cpp Java_com_mob_test_jni_testjni_JNIMethods_stringFromJNI");
return stringFromJNIDis(env, jobj);
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_mob_test_jni_testjni_JNIMethods_testParams(JNIEnv *env, jclass type, jint jint_, jstring jstring_, jobject jobject_,
jobjectArray arrayObject,
jobject list) {
LOGD("test-jni.cpp Java_com_mob_test_jni_testjni_JNIMethods_testParams");
return testParamsDis(env, type, jint_, jstring_, jobject_, arrayObject, list);
}
//显式注册
jstring stringFromJNIDis(JNIEnv *env, jobject jobj) {
LOGD("test-jni.cpp stringFromJNIDis");
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
jstring testParamsDis(JNIEnv *env, jclass type, jint jint_, jstring jstring_, jobject jobject_, jobjectArray arrayObject, jobject list) {
LOGD("test-jni.cpp testParamsDis");
char returnValue[1024];
int i = jint_;
sprintf(returnValue, "%d", i);
appendString(env, returnValue, jstring_);
jstring returnToString = reinterpret_cast<_jstring *>(env->CallObjectMethod(jobject_, methodID_toString));
appendString(env, returnValue, returnToString);
jsize len = env->GetArrayLength(arrayObject);
jobject tmpObject;
jstring tmpString;
for (i = 0; i < len; i++) {
tmpObject = env->GetObjectArrayElement(arrayObject, i);
tmpString = reinterpret_cast<_jstring *>(env->CallObjectMethod(tmpObject, methodID_toString));
appendString(env, returnValue, tmpString);
}
env->DeleteLocalRef(tmpObject);
jclass clazz_list = env->GetObjectClass(list);
jmethodID list_get = env->GetMethodID(clazz_list, "get", "(I)Ljava/lang/Object;");
jmethodID list_size = env->GetMethodID(clazz_list, "size", "()I");
int size = env->CallIntMethod(list, list_size);
jstring itemStr;
for (i = 0; i < size; i++) {
itemStr = reinterpret_cast(env->CallObjectMethod(list, list_get, i));
appendString(env, returnValue, itemStr);
}
return env->NewStringUTF(returnValue);
}
3. 在gradle中设置cmake编译选项,并编写CMakeLists.txt剧本,用于天生so
android {
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
#CMakeList.txt 内容如下:
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
set(distribution_DIR ${CMAKE_SOURCE_DIR}/src/main/cpp)
add_library( # Sets the name of the library.
test-jni
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/test-jni.cpp)
find_library( # Sets the name of the path variable.
test
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
target_link_libraries( # Specifies the target library.
test-jni
# Links the target library to the log library
# included in the NDK.
${log-lib} )
4. 在java层,加载当地要领前,加载so
public class JNIMethods {
static {
//加载so
System.loadLibrary("test-jni");
}
//隐式注册
public native String stringFromJNI();
public static native String testParams(int jint, String jstring, Object jobject, Object[] arrayObject, Listlist);
//显式注册
public native String stringFromJNIDis();
public static native String testParamsDis(int jint, String jstring, Object jobject, Object[] arrayObject, Listlist);
}
so加载流程
一样平常我们是通过 System.loadLibrary("test-jni") 的方式来加载libtest-jni.so库的,一起来跟踪下整个加载历程(此处剖析的源码是基于Dalvik的)
System.loadLibrary() -> Runtime.loadLibray0() -> Runtime.doLoad() -> Runtime.nativeLoad()
//java.lang.System
public static void loadLibrary(String libname) {
Runtime.getRuntime().loadLibrary0(VMStack.getCallingClassLoader(), libname);
}
//java.lang.Runtime
synchronized void loadLibrary0(ClassLoader loader, String libname) {
//......
String error = doLoad(filename, loader);
//......
}
private String doLoad(String name, ClassLoader loader) {
//......
synchronized (this) {
return nativeLoad(name, loader, librarySearchPath);
}
}
// TODO: should be synchronized, but dalvik doesn't support synchronized internal natives.
“沈阳软件公司”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与
我们联系删除或处理,客服QQ:55506560,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同
其观点或证实其内容的真实性。
热门文章
使用“扫一扫”即可将网页分享至朋友圈。