關於JNI 和JAVA 編碼的問題小結

      關於JNI JAVA 編碼的問題小結<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

好久不寫博客,最近發生了好多的事情,但是我還是希望精誠所至金石爲開,能讓我有個很美好的結局。最近在研究JavaC之間的通過JNI進行調用的問題,所以今天總結一下存檔,也方便以後翻出來重讀。

 

總的來說呢,都是關於編碼的問題,具體的問題如下:在Linux下,寫了簡單的c 來調用java,這樣的程式很多,大家也可以看/jdk/src/java.c,也是個很好的例子。我的情況如下,在call java的程式之後,發現下面的語句執行失敗:

 

Int itmp;

Itmp = sprintf(s,”%s”str);

 

其中strbig5的編碼“測試程式”, 執行完後s爲空,itmp = -1

Os: en_US.UTF-8, 

 

然後就查找sprintfmsdn

The number of characters written, or –1 if an error occurred. If buffer or format is a null pointer, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, these functions return -1 and set errno to EINVAL.

 

所以添加如下代碼來排錯:

 

Char *s;

S = setlocale(LC_CTYPE,(char *)NULL);

S = setlocale(LC_ALL,(char*)NULL);

 

查看調用java和不調用java的區別:如果不調用java,那麼LC_CTYPE”C”,如果調用java,那麼LC_CTYPE=en_US.UTF-8

 

哦,原來是JNI_CreateJavaVM 調用之後,修改了LC_CTYPE的值。

 

所以問題的本質就產生了:os的編碼設置和自己程序中的編碼不一致的時候,應該怎麼辦??

 

當然很多人都會說:修改環境變量LANG的值 LANG=zh_TW,或者修改LC_CTYPE=zh_TW,但是有些情況,我們不希望爲了執行我們自己的程序而修改整個的環境變量。

當然如果能夠在啓動JVM的時候指定編碼就好了,可是我在JavaVMInitArgs嘗試添加user.language=zh user.region=CN sun.jnu.encoding=GBK,仍然不起任何作用,LC_CTYPE依然爲en_US.UTF-8,看樣子這種客戶端版本的jre就是和os相關,不能手工設置,當然一些server版的可以自己設置。

目前我們想到的解決的辦法是call 完 java之後,調用setlocale將值設回之前的值。目前不知道這種解決的辦法是否會引起錯誤。

 

我看了一些網上的說法:

.java可以是任意的編碼。

通過javac編譯的時候可以指定編碼例如: javac –encoding 來指定編碼。比如javac   -encoding   big5   abc.java   或者javac   -encoding   gb2312   abc.java  

 

由於JDK是國際版的,在編譯的時候,如果我們沒有用-encoding參數指定我們的JAVA源程序的編碼格式,則javac.exe首先獲得我們操作系統默認採用的編碼格式,也即在編譯java程序時,若我們不指定源程序文件的編碼格式,JDK首先獲得操作系統的file.encoding參數(它保存的就是操作系統默認的編碼格式,如WIN2k,它的值爲GBK),然後JDK就把我們的java源程序從file.encoding編碼格式轉化爲JAVA內部默認的UNICODE格式放入內存中。然後,javac把轉換後的unicode格式的文件進行編譯成.class類文件,此時.class文件是UNICODE編碼的,它暫放在內存中,緊接着,JDK將此以UNICODE編碼的編譯後的class文件保存到我們的操作系統中形成我們見到的.class文件。對我們來說,我們最終獲得的.class文件是內容以UNICODE編碼格式保存的類文件,它內部包含我們源程序中的中文字符串,只不過此時它己經由file.encoding格式轉化爲UNICODE格式。

 

我在網上看到一些帖子中說 .class 文件是UTF-8的格式,我猜想是因爲UCS-2LITTLE ENDIAN BIG endian的區別,所以不能夠完全的跨平臺,而UTF-8則是完全的跨平臺。

通過java來解釋執行.class文件,其實就是通過C來啓動JVM來解釋執行,就是通過UCS-2來進行通信,最後的結果由於要在OS上顯示,所以需要將UCS-2轉換爲LOCALE來顯示在OS上。

也不知道我的理解是否正確。O(_)O哈哈~

 

如果想要學習JNI,可以在這個網址上找到一些有用的信息:

http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-12.html

http://java.sun.com/j2se/<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />1.4.2/docs/guide/jni/index.html

發佈了50 篇原創文章 · 獲贊 7 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章