分类:
2008-09-10 10:08:59
简 介
你遇到JNI和Cygwin的问题吗?你用Windoes下的JVM不能加载Cygwin下创建的库文件吗?这篇文章将帮助你通过创建JVM启动器来解决这个问题。我假设你对JNI有一个基本的理解。
关于Cygwin
Cygwin是一个为平台开发的类Linux环境。它包含两部分:
1.一个DLL(cygwin1.dll)。它作为Linux API仿真层提供了实质的Linux API功能。
2.Linux风格的工具收集器。使用Cygwin,在Linux下的编译的程序经常几乎不用改变的被交叉变为为win32程序。它也能够帮助在下使用Linux的库函数。
JNI和Cygwin
你试过从java中加载Cygwin jni dll吗?你可能会看到你的应用程序在System.loadLibrary().期间挂起了。原因是在Cygwin下Build的库要依赖cygwin1.dll。如果没有Cygwin使用的进程在运行,那么动态加载依赖于Cygwin(在加载时)的Dll将导致这个进程的死锁。因此我们需要Cygwin进程来启动JVM。这就简单了........!我们用C语言创建一个启动器然后在Cygwin下编译连接。Cygwin的 Invocation API 工作并允许JVM被启动。
怎样创建(启动)JVM
JDK或JRE中标准的启动器命令(java 或 javaw.exe)就是一个用java虚拟机(JVM)连接的C程序。启动器解释命令行参数加载虚拟机,然后通过invocationg接口运行java应用程序。JVM将来就会成为一个叫做jvm.dll的动态连接库。
在进一步深入之前,让我们来讨论几个创建JVM会用到的结构体和函数
VMInitArgs
java虚拟机的参数,它被定义在jni.h中 如下:
typedef struct JavaVMInitArgs {
/*JVM Version .It must be JNI_VERSION_1_2 or JNI_VERSION_1_4 or JVM will
interpret pointer as a JDK1_1InitArgs*/
jint version;
/*number of JVM options*/
jint nOptions;
JavaVMOption *options;
/*see definition of JavaVMOption below*/
/*JVM option status. if JNI_TRUE, ignore options VM does not understand
otherwise return JNI_ERR if there are any unrecognized options*/
jboolean ignoreUnrecognized;} JavaVMInitArgs;
/*Definition of JavaVMOption*/
typedef struct JavaVMOption {
char *optionString;
/*a string containing the argument*/
/*extra info to the JVM.Not important.*/
void *extraInfo;} JavaVMOption;
JNI_CreateJavaVM
jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args);
第一个参数是指向javaVM指针的指针。javaVM结构体能被用来绑定和分离来往于虚拟机的本地线程,也用来销毁这个虚拟机(从JDK1.4开始销毁虚拟机的方式不被支持了,DestroyJavaVM将一直等待直到除了当前线程还有所有用户线程都死亡之后才返回一个错误号)。第二个参数是一个指向JNIEnv指针的指针。JNIEnv结构体是JNI编程主要的做粗重工作的结构体。粗糙的讲,JNIEnv结构体与一个具体的java线程相对应,JNIEnv结构体由JNI_CreateJavaVM()返回,因此它代表了虚拟机的主线程。第三个参数是一个无类型指针,它包含虚拟机的参数。下面是一个创建虚拟机实例的代码:
JavaVMInitArgs vm_args;
JavaVMOption options[4];
/* disable JIT */
options[0].optionString ="-Djava.compiler=NONE";
/* user classes */
options[1].optionString = "-Djava.class.path=c:\\myclasses";
/* native lib path */
options[2].optionString = "-Djava.library.path=c:\\mylibs";
options[3].optionString = "-verbose:jni"; /* print JNI msgs */
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 4;
vm_args.ignoreUnrecognized = TRUE;
//Pointer to the function JNI_CreateJavaVM
typedef jint (JNICALL CreateJavaVM_t)(JavaVM **pvm, void **env, void *args);
//Load the jvm dll (the jvm !)
HINSTANCE hinst = LoadLibrary("jvm.dll")
//Get the address of the function
CreateJavaVM_t *pfnCreateJavaVM = GetProcAddress(hinst, "JNI_CreateJavaVM");
//Create JVM
Int iRetval = pfnCreateJavaVM((&vm, (void **)&env,
&vm_args);
//Error handling.
if (res < 0) {
... /* error occurred
}
[1]