JNI原生方法命名规则

JNI调用函数命名规则

一、引用

    Oracle文档:https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html  

    Resolving Native Method Names

    Dynamic linkers resolve entries based on their names. A native method name is concatenated from the following components:

  • the prefix Java_
  • a mangled fully-qualified class name
  • an underscore (“_”) separator
  • a mangled method name
  • for overloaded native methods, two underscores (“__”) followed by the mangled argument signature

    The VM checks for a method name match for methods that reside in the native library. The VM looks first for the short name; that is, the name without the argument signature. It then looks for the long name, which is the name with the argument signature. Programmers need to use the long name only when a native method is overloaded with another native method. However, this is not a problem if the native method has the same name as a nonnative method. A nonnative method (a Java method) does not reside in the native library.

    In the following example, the native method g does not have to be linked using the long name because the other method g is not a native method, and thus is not in the native library.

class Cls1 { 

  int g(int i); 

  native int g(double d); 

} 

    We adopted a simple name-mangling scheme to ensure that all Unicode characters translate into valid C function names. We use the underscore (“_”) character as the substitute for the slash (“/”) in fully qualified class names. Since a name or type descriptor never begins with a number, we can use _0, ..., _9 for escape sequences, as Table 2-1 illustrates: 

Table 2-1 Unicode Character Translation
Escape Sequence
Denotes
_0XXXX
a Unicode character  XXXX.
Note that lower case is used
to represent non-ASCII
Unicode characters, e.g.,
_0abcd as opposed to
_0ABCD.
_1
the character “_”
_2
the character “;” in signatures
_3
the character “[“ in signatures

Both the native methods and the interface APIs follow the standard library-calling convention on a given platform. For example, UNIX systems use the C calling convention, while Win32 systems use __stdcall.

Native Method Arguments

    The JNI interface pointer is the first argument to native methods. The JNI interface pointer is of type JNIEnv. The second argument differs depending on whether the native method is static or nonstatic. The second argument to a nonstatic native method is a reference to the object. The second argument to a static native method is a reference to its Java class.

    The remaining arguments correspond to regular Java method arguments. The native method call passes its result back to the calling routine via the return value. Chapter 3 describes the mapping between Java and C types.

Code Example 2-1 illustrates using a C function to implement the native method f. The native method f is declared as follows:

package pkg;  

class Cls { 

     native double f(int i, String s); 

     ... 

} 

    The C function with the long mangled name Java_pkg_Cls_f_ILjava_lang_String_2 implements native method f:

Code Example 2-1 Implementing a Native Method Using C
jdouble Java_pkg_Cls_f__ILjava_lang_String_2 (
     JNIEnv *env,        /* interface pointer */
     jobject obj,        /* "this" pointer */
     jint i,             /* argument #1 */
     jstring s)          /* argument #2 */
{
     /* Obtain a C-copy of the Java string */
     const char *str = (*env)->GetStringUTFChars(env, s, 0);

     /* process the string */
     ...

     /* Now we are done with str */
     (*env)->ReleaseStringUTFChars(env, s, str);

     return ...
}

    Note that we always manipulate Java objects using the interface pointer env . Using C++, you can write a slightly cleaner version of the code, as shown in Code Example 2-2:

Code Example 2-2 Implementing a Native Method Using C++
extern "C" /* specify the C calling convention */  

jdouble Java_pkg_Cls_f__ILjava_lang_String_2 ( 

     JNIEnv *env,        /* interface pointer */ 

     jobject obj,        /* "this" pointer */ 

     jint i,             /* argument #1 */ 

     jstring s)          /* argument #2 */ 

{ 

     const char *str = env->GetStringUTFChars(s, 0); 

     ... 

     env->ReleaseStringUTFChars(s, str); 

     return ... 

} 

    With C++, the extra level of indirection and the interface pointer argument disappear from the source code. However, the underlying mechanism is exactly the same as with C. In C++, JNI functions are defined as inline member functions that expand to their C counterparts.


二、命名规则

从官网文档我们了解到JNI函数的命名规则:

  • java代码中的函数声明需要添加native关键字。
  • native中的函数命名规则Java_包名_类名_自定义函数名_签名。其中包名中的“.”,需要修改成“_”。

    注:VM检查与本地库中驻留的方法匹配的方法名称。VM首先查找短名称; 即没有参数签名的名称。然后它查找长名称,这是带有参数签名的名称。只有当本地方法被另一个本地方法重载时,程序员才需要使用长名称。但是,如果本机方法与非本机方法具有相同的名称,则这不需要。

  • JNI接口指针是本地方法的第一个参数。JNI接口指针的类型是JNIEnv第二个参数根据本地方法是静态还是非静态而不同。非静态本地方法的第二个参数是对该对象的引用。静态本地方法的第二个参数是对其Java类的引用。其余的参数对应于Java方法参数。
  • java方法参数和返回值需要根据对照表进行相应的转换,请参照:java和jni类型对照表

三、android studio快速生成头文件

  • 打开Terminal(控制台)

    View->Tool Windows->Terminal。

  • 跳转到目录:cd app/src/main/java

    

  • 生成JNI头文件

    在控制台输入javah -d . -jni xxxx命令,其中“xxxx”是完整的类路径,例如“com.zzy.ndkdemo.MainActivity”


猜你喜欢

转载自blog.csdn.net/zhao007z5/article/details/80062897