先以一个简单的例子开始。还是程序员熟悉的Hello World程序,只是我们要求显示一个消息框而不是控制台里的文字。这通过在本地方法里调用MessageBox来实现。先看Java代码:
class Hello {
public static native void sayHello(String name);
// 我们要在C语言中实现的本地方法
static {
System.loadLibrary("hello");
// 载入hello.dll库
}
public static void main(String[] argv) {
sayHello("Tommy");
}
}
运行命令java Hello.java生成class文件,再调用javah Hello生产头文件。(对,javah中的‘h’就是header的意思!)这个头文件包括了sayHello的C语言实现的原型。为了简单起见,我们直接修改生产的头文件为:
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Hello
* Method: sayHello
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_Hello_sayHello(JNIEnv* jni_env,
jclass cls,
jstring name) {
const jchar* unicode_name = (*jni_env)->GetStringChars(
jni_env, name, NULL);
// name是Java的String对象,我们需要将其
// 转换为wchar_t的指针。
wchar_t message[20];
swprintf(message, 20, L"Hello %s", unicode_name);
(*jni_env)->ReleaseStringChars(name, unicode_name);
MessageBoxW(NULL, message, L"JNI_TEST", MB_OK);
}
#ifdef __cplusplus
}
#endif
编译:cl /c /I..\src\share\javavm\export Hello.c
link /dll Hello.obj user32.lib jvm.lib。
从这个简单例子里可以看出,和上一篇创建Java虚拟机并运行Java程序的方法是一样的,即调用JNI函数完成我们需要的功能;不同的是在Java本地方法里我们直接获得了JNI的指针,不需要通过创建虚拟机获得它。下文将描述一下JNI提供的主要方法,从这里我们可以看到Java虚拟机的一个大致功能框架。
JNI提供了下述这些功能:
- Java类相关函数,包括DefineClass和FindClass
- 异常相关函数,包括Throw,ThrowNew以及检查异常状态的ExceptionOccurred,ExceptionDescribe和ExceptionClear
- 对象相关函数,包括AllocObject,NewGlobalRef,NewLocalRef,DeleteLocalRef
- 访问对象成员、方法的函数,包括GetFieldID,Get
Field,Set Field,GetMethodID,Call Method和CallNonvirtual Method( 代表成员类型或者方法返回值) - 访问类的成员、方法的函数(即静态成员和方法,和上面类似,只是在Get/Set后加上了Static)字符串相关函数,包括NewString,GetStringLength,GetStringChars,ReleaseStringChars(这一组是操作Unicode字符串的,还有一组是操作UTF8的,在String后面加上UTF)
- 数组相关函数,包括GetArrayLength,NewObjectArray,GetObjectArrayElement,SetObjectArrayElement(这一组是操作对象数组的,对于每个原始类型都有这样的一套函数)
这些函数的用途可以从名字上看出,具体信息请参考这里。
No comments:
Post a Comment