5

在 JNI 函数FindClass的文档中,我可以阅读有关参数名称的信息:

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

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

空字符 (char)0 使用两字节格式而不是一字节格式编码

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

即最后有双'\ 0'?

4

3 回答 3

3

不,您不对终止零进行编码,它不是类名的一部分。

于 2013-08-19T11:14:22.927 回答
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 终止符的 C 函数“处理”修改后的 UTF-8 字符串,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 更String直接Charset用于在 C 函数设计的字符集和编码之间进行转换的类。通常,它是系统设置、用户设置、应用程序设置或线程设置来确定正在使用哪个 C 函数。String当没有为转换指定特定编码时,Java类会尝试符合此类设置。但是,在很多情况下,所需的编码是固定的,可以明确指定。

于 2013-08-19T13:32:51.990 回答
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 提供的 U+0000 的特殊 2 字节编码仅在您想将 U+0000 放在字符串中并且仍然能够将其与 C 终止符区分开来时才重要。

于 2013-08-19T11:01:07.900 回答