2013-08-19 160 views
5

在JNI功能的文档的findClass我可以阅读有关参数JNI字符串和C字符串

名称:该字符串在修改编码的完全合格的类名(...) UTF-8。

根据文档改性UTF-8具有双重“\ 0”字符结束:

空字符(CHAR)0使用两个字节的格式,而不是一维编码字节格式

这是否意味着我应该在C以这种方式调用的findClass: FindClass("java/lang/String\0")

即双“\ 0”在结束了吗?

+2

当你试过时发生了什么,它是否起作用? – mah

+0

@mah问题提出“应该”而不是“可能”。这是关于技术的正确性而不是[“通过巧合编程。”](http://pragprog.com/the-pragmatic-programmer/extracts/coincidence)当然,它的工作原理是正确的,但这并不正确。 –

回答

3

字符集,编码和终止是三个不同的东西。显然,编码是为特定字符集设计的,但字符集可以用多种方式编码。而且,终结者(如果使用的话)通常是一个编码字符,但是修改后的UTF-8并非如此。

Java使用Unicode字符集。对于字符串和字符类型,它使用UTF-16编码。字符串类型被计数;它不使用终止符。

在C中,终止字符串是常见的,以及各种字符集的单字节编码。 C和C++编译器用NUL字符结束文字字符串。在编译器的目标字符集编码中,这是一个或两个0x00字节。几乎所有通用字符集及其编码都具有非控制ASCII字符的相同字节表示形式。 Unicode字符集的UTF-8编码也是如此。 (但是,请注意,对于有限子集以外的字符不适用。)

JNI设计人员选择使用C字符串之间有限的“互操作性”。许多JNI函数接受以0x00结尾的修改的 UTF-8字符串。它们与源代码中的文字字符串所产生的C编译器兼容,同样规定字符限制为非控制ASCII字符。这涵盖了在JNI中编写Java包&类,方法和字段字符串的用例。 (好吧,几乎:Java允许标识符中包含任何Unicode货币符号。)

因此,您可以将C字符串文字传递给所见即所得风格的JNI函数。不需要添加终止符 - 编译器会这样做。 C编译器会将额外的'\ 0'字符编码为0x00,所以它不会造成任何伤害,但不是必需的。

对标准UTF-8编码有一些修改。一种是允许期望0x00终止符能够“处理”修改的UTF-8字符串的C函数,NUL字符(U + 00000)被编码以避免0x00,这将是标准。这允许修改后的UTF-8字符串放置在具有0x00终止符的缓冲区之外,超出原始编码字符串的字节。另一种修改有点深奥,但两种修改都会使修改后的UTF-8字符串与严格符合UTF-8的函数不兼容。

你没有问,但在JNI中有另一种使用0x00终止,修改的UTF-8字符串。它与GetStringUTFCharsNewStringUTF功能。 (JNI文档实际上并没有说GetStringUTFChars返回一个0x00终止的字符串,但没有已知的JVM实现不支持。请检查JVM实现者的文档或源代码。)这些函数的设计基于相同的“互操作性”。但是,用例是不同的,这使得它们很危险。它们通常用于在C函数之间传递Java字符串。一般来说,C函数不知道修改过的UTF-8是什么,甚至可能甚至不知道UTF-8或Unicode是什么。使用Java StringCharset类可以更直接地转换为C函数专用的字符集和编码。通常,这是用于确定C函数正在使用的系统设置,用户设置,应用程序设置或线程设置。 Java String类尝试在未给定转换的特定编码时符合此类设置。但是,在很多情况下,所需的编码是固定的,并且可以用明确的意图来指定。

3

不,according to the first reference I found,这意味着它应该像这样编码:

FindChar("java/lang/String\xc0\x80"); 
          ^
           | 
           | 
        This is not the shortest 
        way to encode the codepoint 
        U+0000, which is why it's 
        "modified" UTF-8. 

注意,这里假设你真的在寻找类名,后缀名为U + 0000,这是相当不可能的。

FindChar("java/lang/String"); 

通过经修订的UTF-8提供的U + 0000的特殊2字节编码只,如果你想很重要:当你从刚刚获得的C字符串应该被终止,就像正常,单0字节把U + 0000放在一个字符串中,并且仍然能够将它与C终结符区分开来。

3

不,你不要编码终止零,它不是类名的一部分。