codefans

          導(dǎo)航

          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          統(tǒng)計(jì)

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          程序設(shè)計(jì)鏈接

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          如何在c,c++中加入java

          Java跨平臺的特性使Java越來越受開發(fā)人員的歡迎,但也往往會聽到不少的抱怨:用Java
          開發(fā)的圖形用戶窗口界面每次在啟動的時候都會跳出一個控制臺窗口,這個控制臺窗口讓
          本來非常棒的界面失色不少。怎么能夠讓通過Java開發(fā)的GUI程序不彈出Java的控制臺窗口
          呢?其實(shí)現(xiàn)在很多流行的開發(fā)環(huán)境例如JBuilder、Eclipse都是使用純Java開發(fā)的集成環(huán)境
          。這些集成環(huán)境啟動的時候并不會打開一個命令窗口,因?yàn)樗褂昧薐NI(Java Native I
          nterface)的技術(shù)。通過這種技術(shù),開發(fā)人員不一定要用命令行來啟動Java程序,可以通
          過編寫一個本地GUI程序直接啟動Java程序,這樣就可避免另外打開一個命令窗口,讓開發(fā)
          的Java程序更加專業(yè)。 



          JNI允許運(yùn)行在虛擬機(jī)的Java程序能夠與其它語言(例如C和C++)編寫的程序或者類庫進(jìn)行
          相互間的調(diào)用。同時JNI提供的一整套的API,允許將Java虛擬機(jī)直接嵌入到本地的應(yīng)用程
          序中。圖1是Sun站點(diǎn)上對JNI的基本結(jié)構(gòu)的描述。 


          圖1 JNI基本結(jié)構(gòu)描述圖





          本文將介紹如何在C/C++中調(diào)用Java方法,并結(jié)合可能涉及到的問題介紹整個開發(fā)的步驟及
          可能遇到的難題和解決方法。本文所采用的工具是Sun公司創(chuàng)建的 Java Development Kit
           (JDK) 版本 1.3.1,以及微軟公司的Visual C++ 6開發(fā)環(huán)境。 





          環(huán)境搭建





          為了讓本文以下部分的代碼能夠正常工作,我們必須建立一個完整的開發(fā)環(huán)境。首先需要
          下載并安裝JDK 1.3.1,其下載地址為“http://java.sun.com”。假設(shè)安裝路徑為C:\JD
          K。下一步就是設(shè)置集成開發(fā)環(huán)境,通過Visual C++ 6的菜單Tools→Options打開選項(xiàng)對話
          框如圖2。 


          圖2 設(shè)置集成開發(fā)環(huán)境圖


          將目錄C:\JDK\include和C:\JDK\include\win32加入到開發(fā)環(huán)境的Include Files目錄中,
          同時將C:\JDK\lib目錄添加到開發(fā)環(huán)境的Library Files目錄中。這三個目錄是JNI定義的
          一些常量、結(jié)構(gòu)及方法的頭文件和庫文件。集成開發(fā)環(huán)境已經(jīng)設(shè)置完畢,同時為了執(zhí)行程
          序需要把Java虛擬機(jī)所用到的動態(tài)鏈接庫所在的目錄C:\JDK \jre\bin\classic設(shè)置到系統(tǒng)
          的Path環(huán)境變量中。這里需要提出的是,某些開發(fā)人員為了方便直接將JRE所用到的DLL文
          件直接拷貝到系統(tǒng)目錄下。這樣做是不行的,將導(dǎo)致初始化Java虛擬機(jī)環(huán)境失敗(返回值
          -1),原因是Java虛擬機(jī)是以相對路徑來尋找所用到的庫文件和其它一些相關(guān)文件的。至
          此整個JNI的開發(fā)環(huán)境設(shè)置完畢,為了讓此次JNI旅程能夠順利進(jìn)行,還必須先準(zhǔn)備一個Ja
          va類。在這個類中將用到Java中幾乎所有有代表性的屬性及方法,如靜態(tài)方法與屬性、數(shù)
          組、異常拋出與捕捉等。我們定義的Java程序(Demo.java)如下,本文中所有的代碼演示都
          將基于該Java程序,代碼如下: 



          package jni.test;

          /**

          * 該類是為了演示JNI如何訪問各種對象屬性等

          * @author liudong

          */

          public class Demo {

          //用于演示如何訪問靜態(tài)的基本類型屬性

          public static int COUNT = 8;

          //演示對象型屬性

          public String msg;

          private int[] counts;

          public Demo() {

          this("缺省構(gòu)造函數(shù)");

          }

          /**

          * 演示如何訪問構(gòu)造器

          */

          public Demo(String msg) {

          System.out.println(":" + msg);

          this.msg = msg;

          this.counts = null;

          }

          /**

          * 該方法演示如何訪問一個訪問以及中文字符的處理

          */

          public String getMessage() {

          return msg;

          }

          /**

          * 演示數(shù)組對象的訪問

          */

          public int[] getCounts() {

          return counts;

          }

          /**

          * 演示如何構(gòu)造一個數(shù)組對象

          */

          public void setCounts(int[] counts) {

          this.counts = counts;

          }

          /**

          * 演示異常的捕捉

          */

          public void throwExcp() throws IllegalAccessException {

          throw new IllegalAccessException("exception occur.");

          }

          }









          初始化虛擬機(jī)





          本地代碼在調(diào)用Java方法之前必須先加載Java虛擬機(jī),而后所有的Java程序都在虛擬機(jī)中
          執(zhí)行。為了初始化Java虛擬機(jī),JNI提供了一系列的接口函數(shù)Invocation API。通過這些A
          PI可以很方便地將虛擬機(jī)加載到內(nèi)存中。創(chuàng)建虛擬機(jī)可以用函數(shù) jint JNI_CreateJavaVM
          (JavaVM **pvm, void **penv, void *args)。對于這個函數(shù)有一點(diǎn)需要注意的是,在JDK
           1.1中第三個參數(shù)總是指向一個結(jié)構(gòu)JDK1_ 1InitArgs, 這個結(jié)構(gòu)無法完全在所有版本的
          虛擬機(jī)中進(jìn)行無縫移植。在JDK 1.2中已經(jīng)使用了一個標(biāo)準(zhǔn)的初始化結(jié)構(gòu)JavaVMInitArgs來
          替代JDK1_1InitArgs。下面我們分別給出兩種不同版本的示例代碼。 



          在JDK 1.1初始化虛擬機(jī): 



          #include 

          int main() {

          JNIEnv *env;

          JavaVM *jvm;

          JDK1_1InitArgs vm_args;

          jint res;

          /* IMPORTANT: 版本號設(shè)置一定不能漏 */

          vm_args.version = 0x00010001;

          /*獲取缺省的虛擬機(jī)初始化參數(shù)*/

          JNI_GetDefaultJavaVMInitArgs(&vm_args);

          /* 添加自定義的類路徑 */

          sprintf(classpath, "%s%c%s",

          vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH);

          vm_args.classpath = classpath;

          /*設(shè)置一些其他的初始化參數(shù)*/

          /* 創(chuàng)建虛擬機(jī) */

          res = JNI_CreateJavaVM(&jvm,&env,&vm_args);

          if (res < 0) {

          fprintf(stderr, "Can't create Java VM\n");

          exit(1);

          }

          /*釋放虛擬機(jī)資源*/

          (*jvm)->DestroyJavaVM(jvm);

          }







          JDK 1.2初始化虛擬機(jī): 



          /* invoke2.c */

          #include 

          int main() {

          int res;

          JavaVM *jvm;

          JNIEnv *env;

          JavaVMInitArgs vm_args;

          JavaVMOption options[3];

          vm_args.version=JNI_VERSION_1_2;//這個字段必須設(shè)置為該值

          /*設(shè)置初始化參數(shù)*/

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

          options[1].optionString = "-Djava.class.path=."; 

          options[2].optionString = "-verbose:jni"; //用于跟蹤運(yùn)行時的信息

          /*版本號設(shè)置不能漏*/

          vm_args.version = JNI_VERSION_1_2;

          vm_args.nOptions = 3;

          vm_args.options = options;

          vm_args.ignoreUnrecognized = JNI_TRUE;

          res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

          if (res < 0) {

          fprintf(stderr, "Can't create Java VM\n");

          exit(1);



          (*jvm)->DestroyJavaVM(jvm);

          fprintf(stdout, "Java VM destory.\n");

          }







          為了保證JNI代碼的可移植性,建議使用JDK 1.2的方法來創(chuàng)建虛擬機(jī)。JNI_CreateJavaVM
          函數(shù)的第二個參數(shù)JNIEnv *env,就是貫穿整個JNI始末的一個參數(shù),因?yàn)閹缀跛械暮瘮?shù)
          都要求一個參數(shù)就是JNIEnv *env。 





          訪問類方法





          初始化了Java虛擬機(jī)后,就可以開始調(diào)用Java的方法。要調(diào)用一個Java對象的方法必須經(jīng)
          過幾個步驟: 



          1.獲取指定對象的類定義(jclass) 



          有兩種途徑來獲取對象的類定義:第一種是在已知類名的情況下使用FindClass來查找對應(yīng)
          的類。但是要注意類名并不同于平時寫的Java代碼,例如要得到類jni.test.Demo的定義必
          須調(diào)用如下代碼: 



          jclass cls = (*env)->FindClass(env, "jni/test/Demo"); //把點(diǎn)號換成斜杠


          然后通過對象直接得到其所對應(yīng)的類定義: 
          jclass cls = (*env)-> GetObjectClass(env, obj);

          //其中obj是要引用的對象,類型是jobject







          2.讀取要調(diào)用方法的定義(jmethodID) 



          我們先來看看JNI中獲取方法定義的函數(shù): 



          jmethodID (JNICALL *GetMethodID)(JNIEnv *env, jclass clazz, const char *name, 
          const char *sig);

          jmethodID (JNICALL *GetStaticMethodID)(JNIEnv *env, jclass class, const char 
          *name, const char *sig);



          這兩個函數(shù)的區(qū)別在于GetStaticMethodID是用來獲取靜態(tài)方法的定義,GetMethodID則是
          獲取非靜態(tài)的方法定義。這兩個函數(shù)都需要提供四個參數(shù):env就是初始化虛擬機(jī)得到的J
          NI環(huán)境;第二個參數(shù)class是對象的類定義,也就是第一步得到的obj;第三個參數(shù)是方法
          名稱;最重要的是第四個參數(shù),這個參數(shù)是方法的定義。因?yàn)槲覀冎繨ava中允許方法的
          多態(tài),僅僅是通過方法名并沒有辦法定位到一個具體的方法,因此需要第四個參數(shù)來指定
          方法的具體定義。但是怎么利用一個字符串來表示方法的具體定義呢?JDK中已經(jīng)準(zhǔn)備好一
          個反編譯工具javap,通過這個工具就可以得到類中每個屬性、方法的定義。下面就來看看
          jni.test.Demo的定義: 



          打開命令行窗口并運(yùn)行 javap -s -p jni.test.Demo 得到運(yùn)行結(jié)果如下: 





          Compiled from Demo.java

          public class jni.test.Demo extends java.lang.Object {

          public static int COUNT;

          /* I */

          public java.lang.String msg;

          /* Ljava/lang/String; */

          private int counts[];

          /* [I */

          public jni.test.Demo();

          /* ()V */

          public jni.test.Demo(java.lang.String);

          /* (Ljava/lang/String;)V */

          public java.lang.String getMessage();

          /* ()Ljava/lang/String; */

          public int getCounts()[];

          /* ()[I */

          public void setCounts(int[]);

          /* ([I)V */

          public void throwExcp() throws java.lang.IllegalAccessException;

          /* ()V */

          static {};

          /* ()V */

          }









          我們看到類中每個屬性和方法下面都有一段注釋。注釋中不包含空格的內(nèi)容就是第四個參
          數(shù)要填的內(nèi)容(關(guān)于javap具體參數(shù)請查詢JDK的使用幫助)。下面這段代碼演示如何訪問jn
          i.test.Demo的getMessage方法: 





          /*

          假設(shè)我們已經(jīng)有一個jni.test.Demo的實(shí)例obj 

          */

          jmethodID mid;

          jclass cls = (*env)-> GetObjectClass (env, obj); //獲取實(shí)例的類定義

          mid=(*env)->GetMethodID(env,cls,"getMessage"," ()Ljava/lang/String; ");

          /*如果mid為0表示獲取方法定義失敗*/

          jstring msg = (*env)-> CallObjectMethod(env, obj, mid);

          /*

          如果該方法是靜態(tài)的方法那只需要將最后一句代碼改為以下寫法即可:

          jstring msg = (*env)-> CallStaticObjectMethod(env, cls, mid);

          */









          3.調(diào)用方法 



          為了調(diào)用對象的某個方法,可以使用函數(shù)CallMethod或者CallStaticMethod(訪問類的靜
          態(tài)方法),根據(jù)不同的返回類型而定。這些方法都是使用可變參數(shù)的定義,如果訪問某個
          方法需要參數(shù)時,只需要把所有參數(shù)按照順序填寫到方法中就可以。在講到構(gòu)造函數(shù)的訪
          問時,將演示如何訪問帶參數(shù)的構(gòu)造函數(shù)。 





          訪問類屬性





          訪問類的屬性與訪問類的方法大體上是一致的,只不過是把方法變成屬性而已。 



          1.獲取指定對象的類(jclass) 



          這一步與訪問類方法的第一步完全相同,具體使用參看訪問類方法的第一步。 



          2.讀取類屬性的定義(jfieldID) 



          在JNI中是這樣定義獲取類屬性的方法的: 





          jfieldID (JNICALL *GetFieldID)

          (JNIEnv *env, jclass clazz, const char *name, const char *sig);

          jfieldID (JNICALL *GetStaticFieldID)

          (JNIEnv *env, jclass clazz, const char *name, const char *sig);


          這兩個函數(shù)中第一個參數(shù)為JNI環(huán)境;clazz為類的定義;name為屬性名稱;第四個參數(shù)同
          樣是為了表達(dá)屬性的類型。前面我們使用javap工具獲取類的詳細(xì)定義的時候有這樣兩行:
            public java.lang.String msg;

          /* Ljava/lang/String; */


          其中第二行注釋的內(nèi)容就是第四個參數(shù)要填的信息,這跟訪問類方法時是相同的。 



          3.讀取和設(shè)置屬性值 



          有了屬性的定義要訪問屬性值就很容易了。有幾個方法用來讀取和設(shè)置類的屬性,它們是
          :GetField、SetField、GetStaticField、SetStaticField。比如讀取Demo類的msg屬性就
          可以用GetObjectField,而訪問COUNT用GetStaticIntField,相關(guān)代碼如下: 





          jfieldID field = (*env)->GetFieldID(env,obj,"msg"," Ljava/lang/String;");

          jstring msg = (*env)-> GetObjectField(env, cls, field); //msg就是對應(yīng)Demo的msg


          jfieldID field2 = (*env)->GetStaticFieldID(env,obj,"COUNT","I");

          jint count = (*env)->GetStaticIntField(env,cls,field2);











          訪問構(gòu)造函數(shù)





          很多人剛剛接觸JNI的時候往往會在這一節(jié)遇到問題,查遍了整個jni.h看到這樣一個函數(shù)
          NewObject,它應(yīng)該是可以用來訪問類的構(gòu)造函數(shù)。但是該函數(shù)需要提供構(gòu)造函數(shù)的方法定
          義,其類型是jmethodID。從前面的內(nèi)容我們知道要獲取方法的定義首先要知道方法的名稱
          ,但是構(gòu)造函數(shù)的名稱怎么來填寫呢?其實(shí)訪問構(gòu)造函數(shù)與訪問一個普通的類方法大體上
          是一樣的,惟一不同的只是方法名稱不同及方法調(diào)用時不同而已。訪問類的構(gòu)造函數(shù)時方
          法名必須填寫“”(注, 我使用的時候發(fā)現(xiàn)應(yīng)該是設(shè)置為NULL)。下面的代碼演示如何構(gòu)造一個Demo類的實(shí)例: 





          jclass cls = (*env)->FindClass(env, "jni/test/Demo");

          /** 

          首先通過類的名稱獲取類的定義,相當(dāng)于Java中的Class.forName方法

          */

          if (cls == 0) 



          jmethodID mid = (*env)->GetMethodID(env,cls,"","(Ljava/lang/String;)V ");

          if(mid == 0)



          jobject demo = jenv->NewObject(cls,mid,0);

          /**

          訪問構(gòu)造函數(shù)必須使用NewObject的函數(shù)來調(diào)用前面獲取的構(gòu)造函數(shù)的定義

          上面的代碼我們構(gòu)造了一個Demo的實(shí)例并傳一個空串null

          */


          數(shù)組處理

          創(chuàng)建一個新數(shù)組 
          要創(chuàng)建一個數(shù)組,我們首先應(yīng)該知道數(shù)組元素的類型及數(shù)組長度。JNI定義了一批數(shù)組的類
          型jArray及數(shù)組操作的函數(shù)NewArray,其中就是數(shù)組中元素的類型。例如,要創(chuàng)建一個大
          小為10并且每個位置值分別為1-10的整數(shù)數(shù)組,編寫代碼如下: 





          int i = 1;

          jintArray array; //定義數(shù)組對象

          (*env)-> NewIntArray(env, 10);

          for(; i<= 10; i++) 

          (*env)->SetIntArrayRegion(env, array, i-1, 1, &i);









          訪問數(shù)組中的數(shù)據(jù) 



          訪問數(shù)組首先應(yīng)該知道數(shù)組的長度及元素的類型。現(xiàn)在我們把創(chuàng)建的數(shù)組中的每個元素值
          打印出來,代碼如下: 





          int i;

          /* 獲取數(shù)組對象的元素個數(shù) */

          int len = (*env)->GetArrayLength(env, array);

          /* 獲取數(shù)組中的所有元素 */

          jint* elems = (*env)-> GetIntArrayElements(env, array, 0);

          for(i=0; i< len; i++)

          printf("ELEMENT %d IS %d\n", i, elems[i]);





          中文處理

          中文字符的處理往往是讓人比較頭疼的事情,特別是使用Java語言開發(fā)的軟件,在JNI這個
          問題更加突出。由于Java中所有的字符都是Unicode編碼,但是在本地方法中,例如用VC編
          寫的程序,如果沒有特殊的定義一般都沒有使用Unicode的編碼方式。為了讓本地方法能夠
          訪問Java中定義的中文字符及Java訪問本地方法產(chǎn)生的中文字符串,我定義了兩個方法用
          來做相互轉(zhuǎn)換。 



          · 方法一,將Java中文字符串轉(zhuǎn)為本地字符串 



          /**

          第一個參數(shù)是虛擬機(jī)的環(huán)境指針

          第二個參數(shù)為待轉(zhuǎn)換的Java字符串定義

          第三個參數(shù)是本地存儲轉(zhuǎn)換后字符串的內(nèi)存塊

          第三個參數(shù)是內(nèi)存塊的大小

          */

          int JStringToChar(JNIEnv *env, jstring str, LPTSTR desc, int desc_len)

          {

          int len = 0;

          if(desc==NULL||str==NULL)

          return -1;

          //在VC中wchar_t是用來存儲寬字節(jié)字符(UNICODE)的數(shù)據(jù)類型

          wchar_t *w_buffer = new wchar_t[1024];

          ZeroMemory(w_buffer,1024*sizeof(wchar_t));

          //使用GetStringChars而不是GetStringUTFChars

          wcscpy(w_buffer,env->GetStringChars(str,0));

          env->ReleaseStringChars(str,w_buffer);

          ZeroMemory(desc,desc_len);

          //調(diào)用字符編碼轉(zhuǎn)換函數(shù)(Win32 API)將UNICODE轉(zhuǎn)為ASCII編碼格式字符串

          //關(guān)于函數(shù)WideCharToMultiByte的使用請參考MSDN

          len = WideCharToMultiByte(CP_ACP,0,w_buffer,1024,desc,desc_len,NULL,NULL);

          //len = wcslen(w_buffer);

          if(len>0 && len 
          desc[len]=0;

          delete[] w_buffer;

          return strlen(desc);

          }







          · 方法二,將C的字符串轉(zhuǎn)為Java能識別的Unicode字符串 



          jstring NewJString(JNIEnv* env,LPCTSTR str)

          {

          if(!env || !str)

          return 0;

          int slen = strlen(str);

          jchar* buffer = new jchar[slen];

          int len = MultiByteToWideChar(CP_ACP,0,str,strlen(str),buffer,slen);

          if(len>0 && len < slen)

          buffer[len]=0;

          jstring js = env->NewString(buffer,len);

          delete [] buffer;

          return js;

          }



          異常





          由于調(diào)用了Java的方法,因此難免產(chǎn)生操作的異常信息。這些異常沒有辦法通過C++本身的
          異常處理機(jī)制來捕捉到,但JNI可以通過一些函數(shù)來獲取Java中拋出的異常信息。之前我們
          在Demo類中定義了一個方法throwExcp,下面將訪問該方法并捕捉其拋出來的異常信息,代
          碼如下: 



          /**

          假設(shè)我們已經(jīng)構(gòu)造了一個Demo的實(shí)例obj,其類定義為cls

          */

          jthrowable excp = 0; /* 異常信息定義 */

          jmethodID mid=(*env)->GetMethodID(env,cls,"throwExcp","()V");

          /*如果mid為0表示獲取方法定義失敗*/

          jstring msg = (*env)-> CallVoidMethod(env, obj, mid);

          /* 在調(diào)用該方法后會有一個IllegalAccessException的異常拋出 */

          excp = (*env)->ExceptionOccurred(env);

          if(excp){ 

          (*env)->ExceptionClear(env);

          //通過訪問excp來獲取具體異常信息

          /*

          在Java中,大部分的異常信息都是擴(kuò)展類java.lang.Exception,因此可以訪問excp的toS
          tring

          或者getMessage來獲取異常信息的內(nèi)容。訪問這兩個方法同前面講到的如何訪問類的方法
          是相同的。

          */

          }


          線程和同步訪問

          有些時候需要使用多線程的方式來訪問Java的方法。我們知道一個Java虛擬機(jī)是非常消耗
          系統(tǒng)的內(nèi)存資源,差不多每個虛擬機(jī)需要內(nèi)存大約在20MB左右。為了節(jié)省資源要求每個線
          程使用的是同一個虛擬機(jī),這樣在整個的JNI程序中只需要初始化一個虛擬機(jī)就可以了。所
          有人都是這樣想的,但是一旦子線程訪問主線程創(chuàng)建的虛擬機(jī)環(huán)境變量,系統(tǒng)就會出現(xiàn)錯
          誤對話框,然后整個程序終止。 



          其實(shí)這里面涉及到兩個概念,它們分別是虛擬機(jī)(JavaVM *jvm)和虛擬機(jī)環(huán)境(JNIEnv *e
          nv)。真正消耗大量系統(tǒng)資源的是jvm而不是env,jvm是允許多個線程訪問的,但是env只
          能被創(chuàng)建它本身的線程所訪問,而且每個線程必須創(chuàng)建自己的虛擬機(jī)環(huán)境env。這時候會有
          人提出疑問,主線程在初始化虛擬機(jī)的時候就創(chuàng)建了虛擬機(jī)環(huán)境env。為了讓子線程能夠創(chuàng)
          建自己的env,JNI提供了兩個函數(shù):AttachCurrentThread和DetachCurrentThread。下面
          代碼就是子線程訪問Java方法的框架: 



          DWORD WINAPI ThreadProc(PVOID dwParam)

          {

          JavaVM jvm = (JavaVM*)dwParam; /* 將虛擬機(jī)通過參數(shù)傳入 */

          JNIEnv* env;

          (*jvm)-> AttachCurrentThread(jvm, (void**)&env, NULL);

          .........

          (*jvm)-> DetachCurrentThread(jvm);

          }


          時間

          關(guān)于時間的話題是我在實(shí)際開發(fā)中遇到的一個問題。當(dāng)要發(fā)布使用了JNI的程序時,并不一
          定要求客戶要安裝一個Java運(yùn)行環(huán)境,因?yàn)榭梢栽诎惭b程序中打包這個運(yùn)行環(huán)境。為了讓
          打包程序利于下載,這個包要比較小,因此要去除JRE(Java運(yùn)行環(huán)境)中一些不必要的文
          件。但是如果程序中用到Java中的日歷類型,例如java.util.Calendar等,那么有個文件
          一定不能去掉,這個文件就是[JRE]\lib\tzmappings。它是一個時區(qū)映射文件,一旦沒有
          該文件就會發(fā)現(xiàn)時間操作上經(jīng)常出現(xiàn)與正確時間相差幾個小時的情況。下面是打包JRE中必
          不可少的文件列表(以Windows環(huán)境為例),其中[JRE]為運(yùn)行環(huán)境的目錄,同時這些文件之
          間的相對路徑不能變。 

          文件名 目錄 

          hpi.dll [JRE]\bin 

          ioser12.dll [JRE]\bin 

          java.dll [JRE]\bin 

          net.dll [JRE]\bin 

          verify.dll [JRE]\bin 

          zip.dll [JRE]\bin 

          jvm.dll [JRE]\bin\classic 

          rt.jar [JRE]\lib 

          tzmappings [JRE]\lib 

          由于rt.jar有差不多10MB,但是其中有很大一部分文件并不需要,可以根據(jù)實(shí)際的應(yīng)用情
          況進(jìn)行刪除。例如程序如果沒有用到Java Swing,就可以把涉及到Swing的文件都刪除后重
          新打包。 

          posted on 2005-11-06 14:26 春雷的博客 閱讀(479) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 北票市| 碌曲县| 绥棱县| 革吉县| 揭阳市| 灯塔市| 稻城县| 轮台县| 乌拉特后旗| 金塔县| 乌恰县| 瑞金市| 长乐市| 朝阳区| 灵台县| 琼海市| 咸丰县| 柘荣县| 准格尔旗| 赤壁市| 滨海县| 交城县| 合作市| 尉氏县| 邯郸市| 吴川市| 饶河县| 白玉县| 滦南县| 合江县| 二手房| 永安市| 紫金县| 新平| 邵武市| 常宁市| 德令哈市| 香河县| 芷江| 聂荣县| 黄陵县|