JNI字符串和C字符串

5
在 JNI 函数 FindClass 的文档中,我可以看到关于参数 name 的说明:

name:一个全限定类名(...),字符串以修改过的 UTF-8 编码。

根据文档,修改过的 UTF-8 必须以双 '\0' 字符结束:

空字符(char)0 使用双字节格式编码,而不是单字节格式

这是否意味着我应该以这种方式从 C 中调用 FindClass:FindClass("java/lang/String\0")
也就是说,在末尾加上双 '\0'?

2
当你尝试过后发生了什么情况?它是否成功了? - mah
@mah 这个问题问的是“应该”而不是“能否”。它关乎技术上的正确性,而非“巧合编程”。当然,这样做可以运行,但并不代表它是正确的。 - Tom Blodget
3个回答

3

根据我找到的第一份参考资料(链接),并不是这样编码:

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结尾的类名,这种情况相当不太可能。C字符串应该像正常情况一样终止,只需使用单个0字节,就像从以下代码得到的一样:
FindChar("java/lang/String");

Modified UTF-8的特殊2字节编码只有在您想将U+0000放入字符串中,并仍能区分它与C终止符时才起作用。


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

3
字符集、编码和终止符是三个不同的概念。显然,编码是为了特定的字符集而设计的,但一个字符集可以用多种方式进行编码。通常,终止符(如果使用)是一个编码字符,但对于修改过的UTF-8来说,情况并非如此。
Java使用Unicode字符集。对于字符串和字符类型,它使用UTF-16编码。字符串类型是计数的;它不使用终止符。
在C语言中,终止字符串很常见,各种字符集的单字节编码也很常见。C和C++编译器会用NUL字符终止文字字符串。在编译器的目标字符集编码中,这可能是一个或两个0x00字节。几乎所有常见的字符集及其编码都具有相同的字节表示形式,用于表示非控制ASCII字符。这适用于Unicode字符集的UTF-8编码。(但请注意,对于有限的子集之外的字符,情况并非如此。)
JNI设计者选择使用C字符串之间的这种有限“互操作性”。许多JNI函数接受以0x00结尾的修改过的UTF-8字符串。如果字符仅限于非控制ASCII字符,则这些字符串与C编译器从源代码中生成的文字字符串兼容。这涵盖了在JNI中编写Java包、类、方法和字段字符串的用例。(好吧,几乎:Java允许在标识符中使用任何Unicode货币符号。)
因此,您可以以所见即所得的方式向JNI函数传递C字符串字面量。无需添加终止符-编译器会自动添加。C编译器将额外的'\0'字符编码为0x00,因此不会造成任何伤害,但也不是必须的。
标准UTF-8编码有一些修改。其中之一是允许C函数处理期望0x00结尾的字符串,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类会尝试符合这些设置。但是,在很多情况下,所需的编码是固定的,并且可以指定明确的意图。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接