java - 如何从 Java 设置环境变量?

标签 java environment-variables

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

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

那么,有没有办法在当前运行的进程中设置环境变量呢?如果是这样,怎么做?如果不是,原因是什么? (是不是因为这是 Java,因此我不应该做邪恶的不可移植的过时的事情,比如触摸我的环境?)如果不是,任何关于管理环境变量更改的好建议,我需要提供给几个子进程?

最佳答案

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

我发现 Edward Campbell 和匿名的两个肮脏 hack 的组合效果最好,因为一个不能在 linux 下工作,另一个不能在 windows 7 下工作。所以为了获得一个多平台的恶意 hack,我将它们结合起来:

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);
      }
    }
  }
}

这就像一个魅力。两位作者的全部功劳。

关于java - 如何从 Java 设置环境变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/318239/

相关文章:

windows - 扩展命令提示符的环境变量

android - 在 Android Studio 中使用 Gradle 构建的环境变量

java - Spring 批处理鸡肉和鸡蛋 : transient JPA reference

java - 我无法从扩展 List 接口(interface)的类中调用方法

r - 使用 .onLoad() 将对象加载到 R 包中的全局环境中

bash - 运行 SQL 时 Bash 中的 `<<-EOSQL` 代码块是什么?

bash - 为什么我不能指定环境变量并在同一命令行中回显它?

java - JSF 和 Maven 的简单示例。无法将托管 bean 消息打印到 xhtml

java - 预期 Android API 级别为 21+,但在使用 Retrofit 2、OkHttp3 时为 19

java - 记录到树