查找远程jvm的默认文件编码

时间:2013-02-17 15:55:07

标签: java character-encoding

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

有没有办法在远程虚拟机上执行Charset.defaultCharset()并获取其值...而不更改远程jvm上运行的程序?

更新:

我试图找出WebLogic 11g或WebLogic 12c服务器的默认Charset是什么...我没有启动,无法重启,我没有“正确”将代码部署到它上面。

我还需要能够从我正在编写的Java程序中确定服务器进程的默认Charset。它可以在与服务器相同的机器上执行......或者不执行。服务器和我的程序将以相同的环境启动是非常值得怀疑的。

我更喜欢一种取决于很少假设的方法......因此通常意味着更多的代码......

我可能无法在服务器上执行Charset.defaultCharset()所以我不应该说'执行Charset.defaultCharset()'。对那些人抱歉。我需要做一些能够提供与在服务器进程内执行Charset.defaultCharset()一样正确的答案。

3 个答案:

答案 0 :(得分:3)

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

特别是强行覆盖file.encoding可能更容易,而不是试图找出它实际上是什么。


正如javadoc of defaultCharset所述:

  

默认字符集是在虚拟机启动期间确定的,通常取决于底层操作系统的区域设置和字符集。

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

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

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

  2. 接下来:在特定主机/ JVM上编译并运行它:

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

    如上所述,如果以相同的方式启动进程,Charset.defaultCharset()应该返回相同的值(在同一主机上)。为了非常接近,您甚至可以使用包含上述代码的jar暂时替换包含main方法的应用程序jar(确保类名匹配)。

  3. 如果这不能提供您需要的信息(它应该),请尝试启动该过程,使其接受调试器,附加调试器,然后深入查看区域设置,和/或执行类似于上面的代码。

  4. 如果仍然没有提供您需要的信息,那么您可以激进并在类加载时使用动态字节码编织。这可以通过基于加载时间编织的现有AOP框架(例如AspectJ),或直接使用ASM 4java.lang.instrument API来实现。请注意,使这项工作存在缺陷,因此很难判断在您的情况下这是否合理简单。但是期望它比上述方法更多(更多?)。

答案 1 :(得分:0)

我建议你使用System.getProperty( "os.name" ),System.getProperty(“os.arch”)来识别远程架构。

The default Charset也可能有用:

java.nio.Charset cs = java.nio.Charset.defaultCharset();

答案 2 :(得分:0)

这是我最终做的......(大致)

  mbs = conn.getMBeanServerConnection();
  ObjectName runtime = new ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);
  TabularDataSupport foo = 
    (TabularDataSupport) mbs.getAttribute(runtime, "SystemProperties");
  for (Iterator<Object> it = foo.values().iterator(); 
                      it.hasNext() && null == retVal; ) {
    CompositeDataSupport cds = (CompositeDataSupport) it.next();
    for (Iterator<?> iter = cds.values().iterator() ; 
                   iter.hasNext() && null == retVal ;) {
      if ("file.encoding".equals(iter.next()) && iter.hasNext())
        retVal = iter.next().toString();
    }

我连接到MBeanServer,然后通过SystemProperties找到连接另一端进程的file.encoding。