一、JNI开发的步骤;
二、静态库和动态库的区别;
三、JNIEnv 是什么?
四、JNI基本数据类型;
五、常用命令:javah, javap;
六、JNI调用Java类对象的字段、非静态方法、静态方法、构造方法;
七、JNI类型签名
==========================================
一、JNI开发的步骤
1.编写native 方法;
2.javah 命令,生成.h 文件(或者自己手写);
java_类的全名_方法名
3.复制.h 头文件到cpp 工程;
4.复制jni.h 和jni_md.h;
5.实现.h 头文件中的声明函数;
6.生成一个.dll /.so动态库;(要配置指定支持的cpu架构类型)
7.在java中加载动态库;
8.调用native函数;
二、静态库和动态库的区别;
函数库分为静态库和动态库两种。
1.静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
2.动态库在程序编译时并不会被连接到目标代码中,而是在程序运行时才被载入,因此在程序运行时还需要动态库存在。
1、 静态函数库
这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。
2、 动态函数库
这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。
三、JNIEnv 是什么?
JNIEnv是一个与线程相关的代表JNI环境的结构体。
JavaVM和JNIEnv的关系:
1、调用JavaVM的AttachCurrentThread函数,就可得到这个线程的JNIEnv结构体。这样可以在后台线程中回调Java函数。
2、在后台线程退出前,需要调用JavaVM的DetachCurrentThread函数来释放对应资源。
/*
* JNI Native Method Interface.
*/
struct JNINativeInterface_;
struct JNIEnv_;
#ifdef __cplusplus
typedef JNIEnv_ JNIEnv;
#else
typedef const struct JNINativeInterface_ *JNIEnv;
#endif
struct JNINativeInterface_ {
void *reserved0;
void *reserved1;
void *reserved2;
void *reserved3;
jint (JNICALL *GetVersion)(JNIEnv *env);
jclass (JNICALL *DefineClass)
(JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
jsize len);
jclass (JNICALL *FindClass)
(JNIEnv *env, const char *name);
.........
};
struct JNIEnv_ {
const struct JNINativeInterface_ *functions;
#ifdef __cplusplus
jint GetVersion() {
return functions->GetVersion(this);
}
jclass DefineClass(const char *name, jobject loader, const jbyte *buf, jsize len) {
return functions->DefineClass(this, name, loader, buf, len);
}
jclass FindClass(const char *name) {
return functions->FindClass(this, name);
}
.........
#endif /* __cplusplus */
};
/*
* We use inlined functions for C++ so that programmers can write:
* env->FindClass("java/lang/String")
* in C++ rather than:
* (*env)->FindClass(env, "java/lang/String")in C.
*/
==================================
* * *
==================================
/*
* JNI Invocation Interface.
*/
struct JNIInvokeInterface_;
struct JavaVM_;
#ifdef __cplusplus
typedef JavaVM_ JavaVM;
#else
typedef const struct JNIInvokeInterface_ *JavaVM;
#endif
struct JNIInvokeInterface_ {
void *reserved0;
void *reserved1;
void *reserved2;
jint (JNICALL *DestroyJavaVM)(JavaVM *vm);
jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);
jint (JNICALL *DetachCurrentThread)(JavaVM *vm);
jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version);
jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args);
};
struct JavaVM_ {
const struct JNIInvokeInterface_ *functions;
#ifdef __cplusplus
jint DestroyJavaVM() {
return functions->DestroyJavaVM(this);
}
jint AttachCurrentThread(void **penv, void *args) {
return functions->AttachCurrentThread(this, penv, args);
}
jint DetachCurrentThread() {
return functions->DetachCurrentThread(this);
}
jint GetEnv(void **penv, jint version) {
return functions->GetEnv(this, penv, version);
}
jint AttachCurrentThreadAsDaemon(void **penv, void *args) {
return functions->AttachCurrentThreadAsDaemon(this, penv, args);
}
#endif
};
1.为什么需要传入JNIEnv,函数执行过程中需要JNIEnv
2.C++为什么没有传入?this
3.C++只是对C的那一套进行的封装,给一个变量赋值为指针,这个变量是二级指针
C/C++中为什么有区别?
四、JNI基本数据类型;
基本数据类型转换
#ifdef HAVE_INTTYPES_H
# include <inttypes.h> /* C99 */
typedef uint8_t jboolean; /* unsigned 8 bits */
typedef int8_t jbyte; /* signed 8 bits */
typedef uint16_t jchar; /* unsigned 16 bits */
typedef int16_t jshort; /* signed 16 bits */
typedef int32_t jint; /* signed 32 bits */
typedef int64_t jlong; /* signed 64 bits */
typedef float jfloat; /* 32-bit IEEE 754 */
typedef double jdouble; /* 64-bit IEEE 754 */
#else
typedef unsigned char jboolean; /* unsigned 8 bits */
typedef signed char jbyte; /* signed 8 bits */
typedef unsigned short jchar; /* unsigned 16 bits */
typedef short jshort; /* signed 16 bits */
typedef int jint; /* signed 32 bits */
typedef long long jlong; /* signed 64 bits */
typedef float jfloat; /* 32-bit IEEE 754 */
typedef double jdouble; /* 64-bit IEEE 754 */
#endif
五、常用命令:javah, javap
1.javah
2.javap -s -p :获取类字段和方法的签名信息
3.javap -s -p -v :可以查看类中方法的descriptor flags;
六、JNI调用Java类对象的字段、非静态方法、静态方法、构造方法
七、JNI类型签名
1、JNI函数签名信息,有参数类型和返回值类型共同组成。
2、为什么需要签名信息
因为Java支持函数重载,即可以定义同名但不同参数的函数。但仅仅根据函数名无法找到具体函数。为了解决这个问题,JNI技术中就将参数类型和返回值类型的组合作为一个函数的签名信息,有了签名信息和函数名,就能准确找到Java中的函数。
3、如何生成函数或变量的签名信息:
javap -s -p xxx
网友评论