一尘不染

如何从Java设置环境变量?

java

如何从Java设置环境变量?我看到我可以使用来对子流程执行此操作ProcessBuilder。不过,我有几个子流程要启动,所以我宁愿修改当前流程的环境,并让这些子流程继承它。

有一个System.getenv(String)获取单个环境变量的方法。我还可以使用获取Map完整的环境变量集System.getenv()。但是,调用put()该方法Map将引发UnsupportedOperationException-显然,这意味着该环境是只读的。而且,没有System.setenv()

那么,有什么方法可以在当前运行的进程中设置环境变量?如果是这样,怎么办?如果没有,有什么根据?(是因为这是Java,所以我不应该像在触摸我的环境那样做邪恶的,不可移植的过时的事情吗?)如果没有,那么管理环境变量更改的任何好的建议都需要反馈给几个子流程?


阅读 643

收藏
2020-02-25

共2个答案

一尘不染

(是因为这是Java,所以我不应该像触摸我的环境那样做邪恶的,不可移植的过时的事情吗?)

我认为你已经打中了头。

减轻负担的一种可能方法是排除一种方法

void setUpEnvironment(ProcessBuilder builder) {
    Map<String, String> env = builder.environment();
    // blah blah
}

ProcessBuilder在启动它们之前通过它。

另外,你可能已经知道这一点,但是可以使用相同的命令启动多个进程ProcessBuilder。因此,如果你的子流程相同,则无需一遍又一遍地进行此设置。

2020-02-25
一尘不染

对于需要为单元测试设置特定环境值的场景,你可能会发现以下技巧很有用。它会在整个JVM中更改环境变量(因此请确保在测试后重置所有更改),但不会更改你的系统环境。

我发现爱德华·坎贝尔和匿名的两个肮脏黑客的组合效果最好,因为其中一个在Linux下不起作用,一个在Windows 7下不起作用。因此,为了获得多平台邪恶的黑客,我将它们结合在一起:

protected static void setEnv(Map<String, String> newenv) throws Exception {
  try {
    Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
    Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
    theEnvironmentField.setAccessible(true);
    Map<String, String> env = (Map<String, String>) theEnvironmentField.get(null);
    env.putAll(newenv);
    Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
    theCaseInsensitiveEnvironmentField.setAccessible(true);
    Map<String, String> cienv = (Map<String, String>)     theCaseInsensitiveEnvironmentField.get(null);
    cienv.putAll(newenv);
  } catch (NoSuchFieldException e) {
    Class[] classes = Collections.class.getDeclaredClasses();
    Map<String, String> env = System.getenv();
    for(Class cl : classes) {
      if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
        Field field = cl.getDeclaredField("m");
        field.setAccessible(true);
        Object obj = field.get(env);
        Map<String, String> map = (Map<String, String>) obj;
        map.clear();
        map.putAll(newenv);
      }
    }
  }
}
2020-02-25