我需要找出Java程序中远程Java vm上的默认文件编码是什么。

有没有一种方法可以在远程vm上执行Charset.defaultCharset()并取回其值...而无需更改在远程jvm上运行的程序?

更新:

我试图找出WebLogic 11g或WebLogic 12c服务器的默认字符集是什么...我没有启动,无法重新启动并且没有将代码部署到其上的“权利”。

我还需要能够从我正在编写的Java程序内部确定服务器进程的默认字符集。它可能与服务器在同一台机器上执行...服务器和我的程序将在同一环境下启动是非常令人怀疑的。

我宁愿使用一种基于很少假设的方法...因此通常意味着更多代码...

我可能无法在服务器上执行Charset.defaultCharset()...因此我不应该说“执行Charset.defaultCharset()”。对不起那个人。我需要做的事情将提供与从服务器进程内部执行Charset.defaultCharset()一样正确的答案。

最佳答案

编辑:写下答案后,我发现它至少部分基于错误的假设,因为不能保证Charset.defaultCharset()总是返回相同的值。只要在与目标应用程序相同的主机上进行尝试,下面的某些方法仍然可以使用,但是我当然建议您也阅读this question的前两个答案以获取更多背景知识。

特别是,强行覆盖file.encoding可能比试图弄清楚它到底是什么要容易。



javadoc of defaultCharset所述:


  默认字符集在虚拟机启动期间确定,通常取决于基础操作系统的语言环境和字符集。


这意味着defaultCharset()在JVM进程内是只读的,并且将为在同一台机器上启动的所有JVM进程返回相同的字符集,除非在启动该进程之前已经明确更改了它们的环境(例如,包装器/启动脚本启动了该进程)。 JVM,并为当前进程及其子级设置不同的语言环境。如果确定两个进程以相同的方式启动,则Charset.defaultCharset()应该返回与您要的应用程序相同的Charset

以此为背景,并按烦恼/努力的顺序增加:


如果主机正在运行Unix / Linux,请尝试procfs。例如。 /proc/<vmpid>/environ/proc/<vmpid>/cmdline(在Linux上)将是个不错的起点,因为它们向您展示了该过程是如何真正启动的,而不会混淆包装脚本。该解决方案还可以获得积分,因为它不需要您重新启动/更改应用程序进行检查。需要注意的事情:LANGLC_*变量(locale on Linux的简介)以及影响区域设置的JVM命令行参数。其他操作系统也可能会进行某种形式的过程检查,您可以用来显示此信息。
下一步:编译并在特定主机/ JVM上运行:

import java.nio.charset.Charset;

public class DumpCharset {
  public static void main(String[] args) {
    System.out.println(Charset.defaultCharset().displayName());
  }
}


如前所述,如果进程以相同的方式启动,Charset.defaultCharset()应该返回相同的值(在同一主机上)。要非常接近,您甚至可以暂时将包含main方法的应用程序jar替换为包含上述代码的jar(确保类名匹配)。
如果那不能为您提供所需的信息(应有),请尝试启动该过程,使其接受调试器,附加调试器,然后深入到区域设置,和/或执行类似于以上代码的表达式。
如果仍然不能为您提供所需的信息,那么您可以大胆地在类加载时使用动态字节码编织。这可以通过基于加载时间编织的现有AOP框架(例如AspectJ)来实现,也可以直接通过ASM 4java.lang.instrument API来实现。请注意,进行这项工作有很多陷阱,因此很难判断这在您的情况下是否相当简单。但是,希望它比上述方法做更多的工作。

关于java - 查找远程jvm的默认文件编码,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14922944/

10-10 10:26