Java JNI围绕java函数及其C实现

时间:2015-09-22 18:43:43

标签: java java-native-interface

我想首先说请不要让我使用javah工具,我写这些jni函数原型比使该工具正常工作更幸运。

我知道我正在正确加载我的jni库,因为它们在我离开类结构时工作。

我有一些包名: 包com.bb.me;

public class test {

  test2 iTest = null;

  public parent test()
  {
    iTest = new test();
    return iTest;
  }

  //putting my native methods here work just fine
  //public native void init();
  //etc

}

上述函数的c jni函数原型如下所示:

JNIEXPORT void JNICALL Java_com_bb_me_test_init(JNIEnv* e, jobject i) {}

如果我通过重命名它inita来破坏上面的函数签名并调用该函数我得到如下错误:

找不到原生Lcom / bb / me / test的实现; .init :()V

另一方面,如果我将本机函数移动到内部类,如下所示:

class test2 extends parent {
//public native void init();
}

然后尝试调用相同的函数,jni会以不同的方式向我抱怨未实现的函数,但这次它看起来像这样:

找不到原生Lcom / bb / me / test $ test2; .init :()V

的实现

我原本以为如果我将jni函数签名编辑成这样的东西:

JNIEXPORT void JNICALL Java_com_bb_me_test_test2_init(JNIEnv* e, jobject i) {}

该功能可以正常工作,但似乎并非如此。

这个jni函数签名中“ $ ”美元符号的含义是什么?

找不到原生Lcom / bb / me / test $ test2; .init :()V

的实现

如何在不使用javah工具的情况下移动此本机函数的位置并更新jni函数签名?

1 个答案:

答案 0 :(得分:3)

  

我想首先说请不要让我使用javah工具,我写这些jni函数原型比使该工具正常工作更幸运。< / p>

我不会要求你使用javah - 虽然很难不这样做 - 但我必须至少说我觉得这句话令人惊讶。我发现javah非常容易使用。如果它不能正常工作&#34;正确&#34;对你来说,我倾向于怀疑你有错误的期望。

  

&#34; $&#34;这个jni函数签名中的美元符号是什么意思?

$从嵌套类的类名称中划分嵌套类的简单名称。这是JVM内部名称表示的一个方面,这是JNI的工作原理。

  

如何在不使用javah工具的情况下移动此本机函数的位置并更新jni函数签名?

您可以参考Oracle's documentation for mapping Java native method names to C function names。期望的本机函数名称基于本机方法类的完全限定JVM名称,基于本机方法的非限定名称,如果它已超载,则基于其签名。如果将本机方法移动到另一个类,则需要更改函数名称以反映新位置,如果尚未完成,则还可能需要将函数签名编码为名称。

内部类的JVM名称为com/bb/me/test$test2。假设该方法没有重载,那么与该类中驻留的本机方法相对应的C函数名称将为Java_com_bb_me_test_00024test2_init()。参数是一个不同的故事 - 它们依赖于Java端方法的参数以及本机方法是否是静态的。我不在这里解决它们。