程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 適合於Cygwin的JVM(java虛擬機)啟動器

適合於Cygwin的JVM(java虛擬機)啟動器

編輯:關於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;

/* disable JIT */

options[0].optionString ="-DJava.compiler=NONE";

/* user classes */

options.optionString = "-DJava.class.path=c:\\myclasses";

/* native lib path */

options.optionString = "-DJava.library.path=c:\\mylibs";

options.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

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 做了測試,可以工作。

http://www.codeproject.com/useritems/cvm/cvm_src.zip

http://www.codeproject.com/useritems/cvm/cvm.zip

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved