TATAMOBILE

缘起

最近分析一个Android平台上的so,发现JNI函数命名如下:

JNI Function Name

函数名字和自己平时写代码不一样,故重新学习JNI方法的签名规则。

规则

工具使用

可以使用javah自动生成JNI函数签名,来探索函数命名规则。

javah -jni 包名.类名

一般类的普通函数

package com.example;
public class Sample{
    public static native int GetSample(int n, String s,int [] arr);
}

执行命令 "javah -jni com.example.Sample" 后生成的c++文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_Sample */

#ifndef _Included_com_example_Sample
#define _Included_com_example_Sample
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_Sample
 * Method:    GetSample
 * Signature: (ILjava/lang/String;[I)I
 */
JNIEXPORT jint JNICALL Java_com_example_Sample_GetSample
  (JNIEnv *, jclass, jint, jstring, jintArray);

#ifdef __cplusplus
}
#endif
#endif

内部类的函数和重载函数

package com.example;

public class Native{
    public static native int GetSample();
    public static native int GetSample(int n, String s,int [] arr);
    public static class Stub{
        public static native int GetSample();
    }
}

执行命令 "javah -jni com.example.Native" 后生成的c++文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_Native */

#ifndef _Included_com_example_Native
#define _Included_com_example_Native
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_Native
 * Method:    GetSample
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_example_Native_GetSample__
  (JNIEnv *, jclass);

/*
 * Class:     com_example_Native
 * Method:    GetSample
 * Signature: (ILjava/lang/String;[I)I
 */
JNIEXPORT jint JNICALL Java_com_example_Native_GetSample__ILjava_lang_String_2_3I
  (JNIEnv *, jclass, jint, jstring, jintArray);

#ifdef __cplusplus
}
#endif
#endif
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_Native_Stub */

#ifndef _Included_com_example_Native_Stub
#define _Included_com_example_Native_Stub
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_Native_Stub
 * Method:    GetSample
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_example_Native_00024Stub_GetSample
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

函数签名

一般函数的JNI接口函数命名:Java_包名_类名_方法名。 比如包com.example下的类Sample中的GetSample函数对应的JNI函数名 : “Java_com_example_Sample_GetSample” 。

重载函数的JNI接口函数命名:Java_包名_类名_方法名__参数签名。 比如包名com.example下的类Native中的GetSample函数对应的JNI函数名: “Java_com_example_Native_GetSample__ILjava_lang_String_2_3I” 。

内部类Stub的JNI函数名: “Java_com_example_Native_00024Stub_GetSample” 。

类型签名

类型签名 Java类型
Z boolean
B byte
C char
S short
I int
J long
F float
D double
Lfully-qulitied-class; 全限定类
[type type[] 数组
(argtypes)rettype 方法类型

转义字符

JNI在函数命名时采用名字扰乱方案,以保证所有的Unicode字符都能转换为有效的C函数名,所有的“/”,无论是包名中的还是全限定类名中的,均使用“_”代替,用_0,…,_9来代替转义字符。

转义字符序列 表示
_0XXXX Unicode字符XXXX
_1 字符“_”
_2 签名中的字符“;”
_3 签名中的字符“[”

比如 "IdsSupplier_00024Stub" 中的"_00024" 表示字符"$" 。

参考资料

tower

tower

Graduated in Computer Science and Engineering, but currently working with GNU/Linux infrastructure and in the spare time I'm an Open Source programmer (Python and C), a drawer and author in the TATAMOBILE Blog.


Comments