关于JNI 和JAVA 编码的问题小结

来源:互联网 发布:base64转化为json格式 编辑:程序博客网 时间:2024/05/17 13:39

      关于JNI JAVA 编码的问题小结

 

好久不写博客,最近发生了好多的事情,但是我还是希望精诚所至金石为开,能让我有个很美好的结局。最近在研究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/1.4.2/docs/guide/jni/index.html

原创粉丝点击