如何从 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/