无需加载库即可调用的Java本机函数

时间:2019-08-15 10:14:00

标签: android-ndk java-native-interface linphone

这是linphone-Android(A Voip SDK)中JNI包装类实现的GitHub链接。

https://github.com/samueljero/linphone-mediastreamer2/blob/master/java/src/org/linphone/mediastream/video/capture/AndroidVideoApi5JniWrapper.java

如您所见,无需使用System.load或System.loadlibrary加载库就可以声明和使用本机函数“ putimage”。

我相信,在JNI方法中,JVM应该能够在运行时找到本机函数实现。而System.load和System.loadlibrary可以完成这项工作。但是怎么可能不加载那样的库呢?

1 个答案:

答案 0 :(得分:0)

不需要调用System.loadSystem.loadLibrary。您可以使用其他方法注册本机代码。

默认情况下,您可以通过构建共享库并加载来导出JNI符号,但是也可以做其他事情。

假设您有本机代码(C)通过创建Java来调用JVM代码。反过来,Java代码调用本机代码。

Java

package recipeNo052;

public class Main {

  public static native int addOne(int a);

  public static void displayMessage() {
    System.out.println("Hello from Java");
    System.out.println(
      "I am calling method without System.load: " + Main.addOne(1));
  }
}

现在,假设您的C代码中有类似的内容(请注意,本机函数具有“正常”名称-没有基于JNI的前缀,等等)

C

JNIEXPORT jint JNICALL addOne(JNIEnv *env, jclass obj, jint a) {
  return a + 1;
}

一旦创建了JVM,就可以执行类似的操作

JNI_CreateJavaVM (&jvm, (void **) &env, &vm_args);

....
....

static JNINativeMethod methods[] = {
  {"addOne",    "(I)I", (void *)&addOne}
};

...
...

jclass cls_Main = (*env)->FindClass (env, "recipeNo052/Main");

...
...

(*env)->RegisterNatives(
  env, 
  cls_Main,
  methods, 
  sizeof(methods)/sizeof(methods[0]));

...
...

现在,每当您调用Main.addOne时,实际上就是从addOne代码中调用main函数。

示例代码

> git clone https://github.com/mkowsiak/jnicookbook.git
> cd jnicookbook/recipeNo052
> make all
> make test
> make clean

您应该得到这样的东西

> make test
lib/recipeNo052_main
Hello from Java
I am calling method without System.load: 2

您可以在此处找到仓库:https://github.com/mkowsiak/jnicookbook.git