適合於Cygwin的JVM(java虛擬機器)啟動器
簡 介
你遇到JNI和Cygwin的問題嗎?你用Windoes下的JVM不能載入Cygwin下建立的庫檔案嗎?這篇文章將協助你通過建立JVM啟動器來解決這個問題。我假設你對JNI有一個基本的理解。
關於Cygwin
Cygwin是一個為Windows平台開發的類Linux環境。它包含兩部分:
1.一個DLL(cygwin1.dll)。它作為Linux API模擬層提供了實質的Linux API功能。
2.Linux風格的工具收集器。使用Cygwin,在Linux下的編譯的程式經常幾乎不用改變的被交叉變為為win32程式。它也能夠協助在Windows下使用Linux的庫函數。
JNI和Cygwin
你試過從java中載入Cygwin jni dll嗎?你可能會看到你的應用程式在System.loadLibrary().期間掛起了。原因是在Cygwin下Build的庫要依賴cygwin1.dll。如果沒有Cygwin使用的進程在運行,那麼動態載入依賴於Cygwin(在載入時)的Dll將導致這個進程的死結。因此我們需要Cygwin進程來啟動JVM。這就簡單了........!我們用C語言建立一個啟動器然後在Cygwin下編譯串連。Cygwin的 Java Invocation API 工作並允許JVM被啟動。
怎樣建立(啟動)JVM
JDK或JRE中標準的啟動器命令(java 或 javaw.exe)就是一個用java虛擬機器(JVM)串連的C程式。啟動器解釋命令列參數載入虛擬機器,然後通過invocationg介面運行java應用程式。JVM將來就會成為一個叫做jvm.dll的動態串連庫。
在進一步深入之前,讓我們來討論幾個建立JVM會用到的結構體和函數
JavaVMInitArgs
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
}
使用這個執行個體
為了能夠啟動任意一個java程式,首先我們必須找到我們指定的類然後我們才能調用這個類的main()方法。我們也可以傳遞參數給我們將要啟動java程式。下面的代碼片斷向我們展示了這些:
//Find the class
<code>
jclass jcJclass = psJNIEnv->FindClass(mainClassName);
//Find the main method id
jmethodID jmMainMethod = psJNIEnv-> GetStaticMethodID(jcJclass, "main", "([Ljava/lang/String;)V");
//Call the main method.
psJNIEnv->CallStaticVoidMethod(jcJclass, jmMainMethod, joApplicationArgs);
使用代碼
這個啟動器的代碼主要是為了在eclipse中使用而寫,現在它還只能處理基本JVM參數。
怎樣編譯?
->開啟 一個 cygwin shell
->運行編譯器. (g++ cvm.cpp -o javaw)
怎樣使用這個啟動器?
*複製這個javaw.exe到你所使用的JRE的bin目錄下(備份你原來的javaw.exe)。確信你在eclipse下使用了這個JRE
*從Cygwin shell啟動eclipse。如果你輸入eclipse,不能啟動,可能是因為PATH沒有設定,你可以做如下設定
export PATH=/cygdrive/c/tools/eclipse3.2/:$PATH
*現在它能不能載入你的JNI 庫,可能是因為PATH沒有設定Close eclipse,通過export命令設定路徑
e.g: export PATH=/cygdrive/c/tutorial/jni_libs/:$PATH
*從你設定了路徑的shell中啟動eclipse
注意:這個啟動器可能不能與所有的JRE/JDK版本工作,因為不同的版本對於JVM的參數是不同的。我用j2re1.4.2_06 做了測試,可以工作。
曆史
Initial Version.
About jafarmlp
|
I am from Tirurangadi, a village of north Kerala,India. I like programming............... Click here to view jafarmlp's online profile. |
Download source files - 4 KbDownload jvm launcher - 6 Kb