当前位置: 首页 > 面试题库 >

从编译到运行时,Java String编码实际上如何工作

漆雕兴平
2023-03-14
问题内容

我最近意识到我不完全了解Java的字符串编码过程。

考虑以下代码:

public class Main
{
    public static void main(String[] args)
    {
        System.out.println(java.nio.charset.Charset.defaultCharset().name());
        System.out.println("ack char: ^"); /* where ^ = 0x06, the ack char */
    }
}

由于Windows-1252和ISO-8859-1之间的控制字符解释不同,因此我选择了ackchar作为测试对象

现在,我使用不同的文件编码,UTF-8,windows-1252和ISO-8859-1对其进行编译。两者都编译为完全相同的东西,由验证md5sum

然后,我运行程序:

$ java Main | hexdump -C
00000000  55 54 46 2d 38 0a 61 63  6b 20 63 68 61 72 3a 20  |UTF-8.ack char: |
00000010  06 0a                                             |..|
00000012

$ java -Dfile.encoding=iso-8859-1 Main | hexdump -C
00000000  49 53 4f 2d 38 38 35 39  2d 31 0a 61 63 6b 20 63  |ISO-8859-1.ack c|
00000010  68 61 72 3a 20 06 0a                              |har: ..|
00000017

$ java -Dfile.encoding=windows-1252 Main | hexdump -C
00000000  77 69 6e 64 6f 77 73 2d  31 32 35 32 0a 61 63 6b  |windows-1252.ack|
00000010  20 63 68 61 72 3a 20 06  0a                       | char: ..|
00000019

0x06无论使用哪种编码,它都能正确输出。

好的,它仍然输出相同的内容0x06,Windows-1252代码页将其解释为可打印的[ACK]字符。

这使我想到了几个问题:

  1. 所编译的Java文件的代码页/字符集是否应与要在其下编译的系统的默认字符集相同?两者总是同义的吗?
  2. 编译后的表示似乎并不依赖于编译时字符集,确实是这样吗?
  3. 这是否意味着如果Java文件中的字符串不对当前字符集/语言环境使用标准字符,那么它们在运行时的解释可能会有所不同?
  4. 关于Java中的字符串和字符编码,我还应该真正了解什么?

问题答案:
  1. 源文件可以采用任何编码
  2. 您需要告诉编译器源文件的编码(例如javac -encoding...);否则,假设平台编码
  3. 在类文件二进制文件中,字符串文字存储为(已修改的)UTF-8,但是除非您使用字节码,否则这无关紧要(请参阅JVM spec)
  4. Java中的字符串始终为UTF-16(请参阅Java语言规范)
  5. System.out PrintStream将改变你的字符串从UTF-16字节之前将其写入编码系统的 标准输出

笔记:

  • 我写的有关Java编码的博客文章
  • 不要使用 -Dfile.encoding


 类似资料:
  • 我在操作系统或编译器优化方面没有深厚的背景,也没有直接使用机器代码,但我开始探索它。我已经开始在assembly中玩了一圈,看看像NASM这样的东西如何将汇编代码编译成机器代码(可执行文件),然后您可以从命令行调用它,比如。 但是JIT编译器实际上是如何在运行时做到这一点的呢?它是像流机器代码到stdin或什么,或者它是如何工作的?如果您能提供一个示例或一些伪代码,说明一些程序集(或类似的东西,但

  • 问题内容: 代码很简单: 有没有办法编译来自标准输出的代码? 我已经试过了: 和一些变体,但没有一个产生可执行文件。 只是一些澄清。我有一个预处理文件的程序,并生成另一个要编译的文件。我考虑过不创建此中间文件,而是直接生成目标文件。 问题答案: 编译器可能会告诉您: 尝试

  • 1. YodaOS Universal 如何配置系统和应用 1.1. 目录 1.1.1. 一.YODAOS完整体验 1.1.2. 定制系统和应用 1.1. 目录 YODAOS 完整体验 如何定制化系统和应用 1.1.1. 一.YODAOS完整体验 下载代码 Yodaos使用git作为源代码管理工具,用Repo 命令行工具管理多个git代码仓库,下载代码时需要用户注册成为Rokid 平台开发者。 注

  • 安装 JDK7 及以上,Maven 3.2.5 及以上。 直接下载代码,然后执行如下命令: cd sofa-rpc mvn clean install 注意:不能在子目录(即子模块)下进行编译。因为 SOFARPC 模块太多,如果每个子模块都会install 和 deploy,仓库内会有较多无用记录。 所以在设计 SOFARPC 工程结构的时候,我们决定各个子模块组件是不需要 install 和

  • 问题内容: 我正在编写一个规则引擎,该引擎执行由条件构造确定的简单分配。规则必须为XML格式,这是项目的先决条件。我已经将XML模式建模为类似于简单的代码块。我希望解析XML,然后将其转换为Java代码。然后,我希望在运行时编译(并运行)此代码。这样做意味着我的规则引擎不再充当解释器,而是执行本机Java字节码。 我已经确定了解析阶段,或多或少的Java代码生成阶段。我现在想弄清楚最后一个阶段-运