Linux 更新后 JVM 中的文件编码错误

Posted

技术标签:

【中文标题】Linux 更新后 JVM 中的文件编码错误【英文标题】:Wrong File Encoding in JVM after Linux Update 【发布时间】:2014-10-22 07:21:42 【问题描述】:

更新linux和java(1.6.0.13->1.6.0.45)后,Java进程使用不同的文件编码(System Property file.encoding)

新的操作系统版本。不幸的是我不知道以前的版本了。但我可以说,更新出错了。我的同事首先使用 x32 操作系统版本进行更新,然后我们重新安装了 x64 版本。

>uname -a
Linux <hostname> 2.6.31.5-0.1-desktop #1 SMP PREEMPT 2009-10-26 15:49:03 +0100 x86_64 x86_64 x86_64 GNU/Linux

区域设置

>locale
LANG=en_US.ISO8859-1
LC_CTYPE=en_US.ISO8859-1
LC_NUMERIC="en_US.ISO8859-1"
LC_TIME="en_US.ISO8859-1"
LC_COLLATE="en_US.ISO8859-1"
LC_MONETARY="en_US.ISO8859-1"
LC_MESSAGES="en_US.ISO8859-1"
LC_PAPER="en_US.ISO8859-1"
LC_NAME="en_US.ISO8859-1"
LC_ADDRESS="en_US.ISO8859-1"
LC_TELEPHONE="en_US.ISO8859-1"
LC_MEASUREMENT="en_US.ISO8859-1"
LC_IDENTIFICATION="en_US.ISO8859-1"
LC_ALL=

测试程序

public class Test

  public static void main(String[] args)
  
    System.out.println(System.getProperty("file.encoding"));
  

如果我启动这个测试程序,它会返回 ANSI_X3.4-1968。在具有相同区域设置的其他机器上,它返回 ISO8859-1。即使我从显式环境变量开始,它也保持不变。唯一可行的解​​决方案是使用 -Dfile.encoding 选项。但我不想调整所有使用 java 的脚本(tomcat、maven、ant、hudson....)。我想恢复旧行为,即 Java 程序中的文件编码是从系统语言环境定义中检索到的。

>java Test
ANSI_X3.4-1968

>LANG=de_DE.ISO8859-1 java Test
ANSI_X3.4-1968

>java -Dfile.encoding=ISO8859-1 Test
ISO8859-1

至少 c 程序得到正确的编码并且不使用 ANSI_X3.4-1968

>idn --debug  --quiet "a.de"
Charset `ISO-8859-1'.
....

有谁知道,如果有任何 jvm 特定设置,可能会在操作系统或 java 更新期间丢失。

任何帮助表示赞赏。

【问题讨论】:

作为最后的手段,Java 配置文件/环境变量 (JAVA_OPTS) 会在每次 JVM 启动时自动读取和应用。如果您无法找到并恢复原始编码,则可以“永久”为所有 Java 应用程序设置这种方式。 您能否更具体地了解 Java 配置文件。我什么都不知道。 JAVA_OPS 似乎不起作用。导出 JAVA_OPTS=-Dfile.encoding=ISO-8859-15 java 测试 ANSI_X3.4-1968。这不适用于 javac 编译器设置,它也使用 ANSI 编码。 我不知道 linux 中的配置文件位置,因为我使用的是 windows。对于JAVA_OPTS,请参见例如***.com/questions/2011311/… 【参考方案1】:

感谢icza。我用谷歌搜索了一下 JAVA_OPTS,发现我应该改用 JAVA_TOOL_OPTIONS。 见How do I use the JAVA_OPTS environment variable?

或_JAVA_OPTIONS: Running java with JAVA_OPTS env variable

对于运行时和编译器来说,两者都工作得很好

>export JAVA_TOOL_OPTIONS=-Dfile.encoding=ISO8859-1
>java Test
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=ISO8859-1
ISO8859-1

>javac Test.java
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=ISO8859-1

>export _JAVA_OPTIONS=-Dfile.encoding=ISO8859-1
>java Test
Picked up _JAVA_OPTIONS: -Dfile.encoding=ISO8859-1
ISO8859-1

>javac Test.java
Picked up _JAVA_OPTIONS: -Dfile.encoding=ISO8859-1

【讨论】:

【参考方案2】:

只需点击类似的东西(在 Debian 上)。这是由于默认 LANG/LC 设置是针对未在 /etc/locale.gen 中配置的语言环境造成的。

为了解决这个问题,我取消了 /etc/locale.gen 中相应行的注释并运行了 sudo locale-gen。

我很惊讶 Java 没有对此给出任何警告。例如,Perl 会发出很大的声音来告诉你有什么东西坏了:

$ LANG=pl_PL.UTF-8 perl -e ''                
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
    LANGUAGE = "en_GB:en",
    LC_ALL = (unset),
    LANG = "pl_PL.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").

另外,为了解释一些其他的行为:ANSI_X3.4-1968 只是一种官方的(并且有些不透明的)表示“ASCII”的方式,而“ISO-8859.1”是“通常”的 8 位超集ASCII 有各种名称,包括“西方”或“拉丁 1”,就 DOS 或旧版本的 Windows 等操作系统而言,它是最接近“标准”字符集的东西。

【讨论】:

以上是关于Linux 更新后 JVM 中的文件编码错误的主要内容,如果未能解决你的问题,请参考以下文章

Linux上无损avi编码

谁能帮我把一个hex文件反编译为c语言文件?

ffmpeg用于将视频编码为H264编解码器格式

在 Linux 上使用 Apache Commons Compression 压缩文件时出现编码错误

jvm类加载

windows怎么跟linux文件服务器进行同步