java - JNI 字符串和 C 字符串

标签 java c++ c java-native-interface

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

name: a fully-qualified class name (...) The string is encoded in modified UTF-8.

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

the null character (char)0 is encoded using the two-byte format rather than the one-byte format

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

即末尾有双'\0'?

最佳答案

字符集、编码和终止是三个不同的东西。显然,编码是为特定的字符集设计的,但是字符集可以用多种方式进行编码。而且,终止符(如果使用的话)通常是一个编码字符,但对于修改后的 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 StringCharset 类在 C 函数设计的字符集和编码之间相互转换更为直接。通常,系统设置、用户设置、应用程序设置或线程设置决定了使用哪个 C 函数。 Java String 类在没有为转换指定特定编码时会尝​​试符合此类设置。但是,在很多情况下,所需的编码是固定的,可以明确指定。

关于java - JNI 字符串和 C 字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18311977/

相关文章:

java - 从 Java 调用 PLSQL 过程

java - 玩! - 独特的模型领域

c++ - 通过 winsock 发送压缩字符串

c++ - 上证所该向上舍入时向下舍入

java - Java 中的异常处理 - Final

java - Mac OS 上安装 Java 的所有位置之间有何区别?

C++ 设计模式平台特定的 api

c - 为什么 objdump 不显示 .bss、.shstratab、.symtab 和 .strtab 部分?

c - 堆栈段和未初始化数据段的区别

c - 不确定我是否需要互斥锁