网站灰色,杭州建站官网建设,洛阳理工学院教务管理系统,公司名称被大量网站收录文章目录 JNI中的JNIEXPORT、JNIIMPORT和JNICALLJVM如何查找native方法①按照JNI规范的命名规则②调用JNI提供的RegsterNatives函数#xff0c;将本地函数注册到JVM中示例代码 JNI数据类型JNI字符串的处理①获取字符串②释放字符串③创建字符串④其他字符串处理API JNI中的JNI… 文章目录 JNI中的JNIEXPORT、JNIIMPORT和JNICALLJVM如何查找native方法①按照JNI规范的命名规则②调用JNI提供的RegsterNatives函数将本地函数注册到JVM中示例代码 JNI数据类型JNI字符串的处理①获取字符串②释放字符串③创建字符串④其他字符串处理API JNI中的JNIEXPORT、JNIIMPORT和JNICALL
两个关键字的定义都可以在jni_md.h下找到
均用于定义与平台相关的宏
用于标识函数用途
JNIEXPORT实则为C规则放置在函数、变量或对象的声明前面指示编译器将其导出为动态链接库的一部分。这使得其他程序可以通过在运行时加载动态链接库并使用导出的函数、变量或对象JNIIMPORT实则为C规则放置在函数、变量或对象的声明前面指示编译器将其标记为从动态链接库中导入的符号JNICALL实则为C规则一种标准的函数调用约定也被称为 “标准调用”具有以下性质 函数的参数按照从右到左的顺序依次入栈。这意味着最右边的参数首先被压入栈中。 调用方清理栈上的参数。这意味着在函数调用结束后由调用方负责从栈上移除函数的参数。 函数的返回值通常存储在 EAX 寄存器中
//Windows下的定义
#define JNIEXPORT __declspec(dllexport)
#define JNIIMPORT __declspec(dllimport)
#define JNICALL __stacall//Linux下的定义实际是空定义
#define JNIEXPORT
#define JNIIMPORT
#define JNICALLJVM如何查找native方法
①按照JNI规范的命名规则
即根据JNI所约定的命名规则来指定函数的命名具体规则如下Java_类全路径_方法名
JNIEXPORT jstring JNICALL Java_com_kqli_jni_JniTest_getStringFromC(JNIEnv *env, jclass jclass);
JNIEXPORT jstring JNICALL Jave_com_test_jni_HelloWord_func(JNIEnv* env, jclass class, jstring str);第一个jstring为返回值string类型函数名中com_kqli_jni_JniTest_getStringFromC代表Java类com_kqli_jni_JniTestgetStringFromC代表具体的函数名称 JNIEnv指向JVM函数表的指针jclass调用Java中native方法的实例对象
②调用JNI提供的RegsterNatives函数将本地函数注册到JVM中
//函数原型
jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods);clazz声明native方法的类methodsJNINativeMethod结构的数组
typedef struct {char *name; //java方法名称char *signature;//java方法签名void *fnPtr;//c/c的函数指针
} JNINativeMethod;nMethods指定methods数组中的本地方法数通常写法为
nMethods sizeof(methods) / sizeof(JNINativeMethod);示例代码
java
package com.test.jni;public class A{static{System.loadLibrary(A); }public static native int a(String str);public static native boolean b();public static native int c(Object obj);public static void main(String[] args){......}
}native
jint a(JNIEnv *env ,jclass class, jstring str){....
}jboolean b(JNIEnv *env ,jclass class){....
}jint c(JNIEnv *env ,jclass class, jobject obj){....
}static JNINativeMethod method_table[]
{{a, (Ljava/lang/String;)I, (void *)a},{b, ()Z, (void *)b},{c, (Ljava/lang/Object;)I, (void *)c},
};jint JNI_OnLoad(JavaVM* vm, void* reserved)
{......jclass clz env -FindClass(JNIREG_CLASS);env -RegisterNatives(clz, method_table, sizeof(method_table) / sizeof(JNINativeMethod));......
}
JNI数据类型 类: 例如String的签名为Ljava/lang/String; 注意: 包名和类名用/隔开, 结尾有一个; 数组用[表示数组签名, 例如int[]的签名为[I JNI字符串的处理
①获取字符串
JNI通过jstring来处理字符串数据但是jstring是指向JVM内部的字符串和C风格的字符串类型char * 不同因此必须使用合适的JNI函数来访问JVM内部的字符串。 因为Java默认使用unicode编码而C/C默认使用UTF编码所以要注意进行编码转换。
const char* GetStringUTFChars(jstring str, jbbolean *isCopy);str为需要获取的字符串isCopy取值JNI_TRUE和JNI_FALSE一般填NULL即可JNI_TRUE返回JVM内部源字符串的拷贝并为新产生的字符串分配内存空间JNI_FALSE返回JVM内部源字符串的指针并可以指针修改源字符串的内容
②释放字符串
通过GetStringUTFChars获取到字符串并返回的为源字符串拷贝后在使用完毕要记得释放内存。
void ReleaseStringUTFChars(jstring str, const char* utf);str为需要释放的字符串指针utf为字节编码
③创建字符串
jstring NewStringUTF(const char * bytes);bytes为C/C的字符串数据源
④其他字符串处理API
GetStringChars、ReleaseStringChars用于获取/释放Unicode格式的字符串GetStringUTFLength、GetStringLength用于获取UTF-8/Unicode格式的字符串长度GetStringCritical、ReleaseStringCritical用于直接返回/释放源字符串的指针获取这个指针会导致暂停GC线程如果GC线程暂停时又被其他线程触发GC的话会出现系统死锁的阻塞调用GetStringUTFRegion、GetStringRegion用于获取UTF-8/Unicode格式字符指定范围内的内容并会将源字符串复制到一个预先分配的缓冲区内