加载中 ...
首页 > 常见问题 正文

干货|JNI实现机制

2019-03-24 10:31:08 来源:沈阳软件公司 作者:沈阳软件开发

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,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同

其观点或证实其内容的真实性。

推荐阅读