rnd*_*rnd 5 c c++ java java-native-interface
在JNI函数FindClass的文档中,我可以读到有关参数名称:
name:完全限定的类名(...)字符串以修改后的UTF-8编码.
根据文档修改,UTF-8必须以双'\ 0'字符结尾:
空字符(char)0使用双字节格式而不是单字节格式进行编码
这是否意味着我应该以这种方式从C调用FindClass:
FindClass("java/lang/String\0")
即最后有两个'\ 0'?
字符集、编码和终止是三个不同的东西。显然,编码是针对特定字符集设计的,但字符集可以通过多种方式进行编码。通常,终止符(如果使用)是编码字符,但对于修改后的 UTF-8,情况并非如此。
\n\nJava 使用 Unicode 字符集。对于字符串和字符类型,它使用 UTF-16 编码。统计字符串类型;它不使用终止符。
\n\n在 C 中,终止字符串以及各种字符集的单字节编码很常见。C 和 C++ 编译器以 NUL 字符终止文字字符串。在编译器的目标字符集编码中,这是一个或两个 0x00 字节。几乎所有常见字符集及其编码对于非控制 ASCII 字符都具有相同的字节表示形式。Unicode 字符集的 UTF-8 编码也是如此。(但是,请注意,对于有限子集之外的字符而言,情况并非如此。)
\n\nJNI 设计者选择在 C 字符串之间使用这种有限的“互操作性”。许多 JNI 函数接受以 0x00 结尾的修改后的UTF-8 字符串。这些与 C 编译器从源代码中的文字字符串生成的内容兼容,同样前提是字符仅限于非控制 ASCII 字符。这涵盖了在 JNI 中编写 Java 包和类、方法和字段字符串的用例。(好吧,几乎是这样:Java 允许在标识符中使用任何 Unicode 货币符号。)
\n\n因此,您可以以所见即所得的方式将 C 字符串文字传递给 JNI 函数。无需添加终止符\xe2\x80\x94,编译器会这样做。C 编译器会将额外的“\\0”字符编码为 0x00,因此不会造成任何损害,但不是必需的。
\n\n标准 UTF-8 编码有一些修改。一种是允许期望 0x00 终止符的 C 函数“处理”修改后的 UTF-8 字符串,NUL 字符 (U+00000) 被编码以避免 0x00,这将是标准。这允许将修改后的 UTF-8 字符串放入缓冲区中,其终止符超出原始编码字符串的字节数。另一种修改有点深奥,但这两种修改都会使修改后的 UTF-8 字符串与严格兼容的 UTF-8 函数不兼容。
\n\n你没有问,但 JNI 中还有另一种以 0x00 结尾、修改过的 UTF-8 字符串的用法。它具有GetStringUTFChars和NewStringUTF功能。(JNI 文档实际上并没有说GetStringUTFChars返回以 0x00 结尾的字符串,但没有已知的 JVM 实现不会这样做。请检查 JVM 实现者的文档或源代码。)这些函数是基于相同的“互操作性”的基础。然而,用例不同,这使得它们很危险。它们通常用于在 C 函数之间传递 Java 字符串。一般来说,C 函数不知道修改后的 UTF-8 是什么,甚至可能不知道 UTF-8 或 Unicode 是什么。String使用 Java和Charset类在 C 函数设计的字符集和编码之间进行转换要直接得多。通常,系统设置、用户设置、应用程序设置或线程设置决定使用哪个 C 函数。当没有为转换指定特定编码时, JavaString类会尝试遵循此类设置。但是,在许多情况下,所需的编码是固定的并且可以以明确的意图指定。
| 归档时间: |
|
| 查看次数: |
1844 次 |
| 最近记录: |