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

Java 查找远程jvm的默认文件编码,java,character-encoding,Java,Character Encoding,我需要找出Java程序中远程Java vm上的默认文件编码是什么 有没有办法在远程vm上执行Charset.defaultCharset()并获取其值。。。不改变远程jvm上运行的程序 更新: 我试图找出WebLogic 11g或WebLogic 12c服务器的默认字符集是什么。。。我没有启动,无法重新启动,并且我没有“权利”在上面部署代码 我还需要能够从我正在编写的Java程序中确定服务器进程的默认字符集。它可能与服务器在同一台计算机上执行。。。或者不是。服务器和我的程序是否会在相同的环境中启

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

有没有办法在远程vm上执行Charset.defaultCharset()并获取其值。。。不改变远程jvm上运行的程序

更新:

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

我还需要能够从我正在编写的Java程序中确定服务器进程的默认字符集。它可能与服务器在同一台计算机上执行。。。或者不是。服务器和我的程序是否会在相同的环境中启动,这是非常值得怀疑的

我更喜欢一种依赖于很少假设的方法。。。所以这通常意味着更多的代码

我可能无法在服务器上执行Charset.defaultCharset()。。。所以我不应该说“execute Charset.defaultCharset()”。对不起,伙计们。我需要做一些事情来提供与从服务器进程内部执行Charset.defaultCharset()一样正确的答案。

我建议您使用System.getProperty(“os.arch”)来识别远程体系结构

也可能有用:

java.nio.Charset cs = java.nio.Charset.defaultCharset();
编辑:在写了我的答案之后,我发现它至少部分地基于一个错误的假设,即
Charset.defaultCharset()
不能保证总是返回相同的值。如果下面的一些方法与目标应用程序在同一主机上进行了尝试,那么它们仍然可以工作,但我当然建议您也阅读的前两个答案,以了解更多背景信息

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


作为缔约国:

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

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

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

  • 如果您的主机运行的是Unix/Linux,请尝试。例如
    /proc//environ
    /proc//cmdline
    (在Linux上)这将是一个很好的起点,因为它们向您展示了流程是如何在不混淆包装脚本的情况下实际启动的。此解决方案还获得了额外的分数,因为它不需要您重新启动/更改应用程序进行检查。需要注意的事项:
    LANG
    LC.*
    变量(简介)和影响语言环境的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(确保类名匹配)

  • 如果这没有提供您需要的信息(它应该提供),请尝试启动该进程,使其接受调试器,附加调试器,然后深入到区域设置,和/或执行类似于上述代码的表达式

  • 如果这仍然不能提供您需要的信息,那么您可以采取激进的做法,在类加载时使用动态字节码编织,或直接与和。请注意,这项工作存在缺陷,因此很难判断在您的情况下这项工作是否合理直接。但预计这项工作(远远?)比上述方法要多


  • 以下是我最后做的…(大致)

    mbs=conn.getMBeanServerConnection();
    ObjectName运行时=新的ObjectName(ManagementFactory.runtime\uMXBean\uName);
    TablerDataSupport foo=
    (TablerDataSupport)mbs.getAttribute(运行时,“系统属性”);
    for(迭代器it=foo.values().Iterator();
    it.hasNext()&&null==retVal;){
    CompositeDataSupport cds=(CompositeDataSupport)it.next();
    for(迭代器iter=cds.values().Iterator();
    iter.hasNext()&&null==retVal;){
    if(“file.encoding”.equals(iter.next())&&iter.hasNext())
    retVal=iter.next().toString();
    }
    

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

    为什么不能修改程序?@alex-w:我没有该程序的源代码it@Jayan:VisualVM有一个API,我可以在我的Java程序中使用它?@vkraemer:它附带了很多插件,不是吗确定如何添加到java程序中。可能有一些东西对您有用。平台是什么?@Jayan:jdk 6,Hotspot VM…如果答案适用于JRockit就好了,但这不是主要要求。看起来所有这些方法都依赖于相同的“如果”:本地Java程序和远程Java程序以相同的方式启动。后两个没有,我一直在谈论远程进程,就像在“同一主机”中一样。
      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();
        }