Android ndk 在不加载库的情况下调用Java本机函数

Android ndk 在不加载库的情况下调用Java本机函数,android-ndk,java-native-interface,linphone,Android Ndk,Java Native Interface,Linphone,这是linphone Android(Voip SDK)中JNI包装类实现的GitHub链接 如您所见,声明并使用本机函数“putimage”,而不使用System.load或System.loadlibrary加载库 我相信在JNI方法中,JVM应该能够在运行时找到本机函数实现。然后System.load和System.loadlibrary完成该工作。但是,如果不这样加载库,怎么办呢?不需要调用System.load或System.loadLibrary。您可以使用不同的方法注册本机代码

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

如您所见,声明并使用本机函数“putimage”,而不使用System.load或System.loadlibrary加载库


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

不需要调用
System.load
System.loadLibrary
。您可以使用不同的方法注册本机代码

默认情况下,您可以通过构建共享库并加载来导出
JNI
符号,但也可以执行其他操作

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

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]));

...
...

> make test
lib/recipeNo052_main
Hello from Java
I am calling method without System.load: 2
现在,无论何时调用
Main.addOne
,实际上都是从
Main
代码调用
addOne
函数

示例代码

> git clone https://github.com/mkowsiak/jnicookbook.git
> cd jnicookbook/recipeNo052
> make all
> make test
> make clean
你应该得到这样的东西

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]));

...
...

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

您可以在这里找到repo:

该过程如何启动JVM?我不理解您的问题。这些包装器将在本地构建到aar中。稍后将在android java代码中使用。从那以后,一切都被构建成一个apk。我对整个本地编程都是新手。我认为ART、DVM和JVM在JNI上的工作方式是一样的。非常感谢您的回复。我不知道可以从本机代码启动JVM。今天,我解决了这个问题。从类定义本身加载库不是强制性的。事实上,在代码中使用该类之前,可以使用不同的方法加载它。JVM稍后将通过损坏的命名约定将其链接到类。是的,您可以使用
LD\u PRELOAD
。通常,您必须确保符号对
JVM
可见。