如何从Java设置环境变量?我看到我可以使用来对子流程执行此操作ProcessBuilder。不过,我有几个子流程要启动,所以我宁愿修改当前流程的环境,并让这些子流程继承它。
有一个System.getenv(String)
获取单个环境变量的方法。我还可以使用获取Map完整的环境变量集System.getenv()
。但是,调用put()该方法Map将引发UnsupportedOperationException
-显然,这意味着该环境是只读的。而且,没有System.setenv()
。
那么,有什么方法可以在当前运行的进程中设置环境变量?如果是这样,怎么办?如果没有,有什么根据?(是因为这是Java,所以我不应该像在触摸我的环境那样做邪恶的,不可移植的过时的事情吗?)如果没有,那么管理环境变量更改的任何好的建议都需要反馈给几个子流程?
(是因为这是Java,所以我不应该像触摸我的环境那样做邪恶的,不可移植的过时的事情吗?)
我认为你已经打中了头。
减轻负担的一种可能方法是排除一种方法
void setUpEnvironment(ProcessBuilder builder) {
Map<String, String> env = builder.environment();
// blah blah
}
并ProcessBuilder
在启动它们之前通过它。
另外,你可能已经知道这一点,但是可以使用相同的命令启动多个进程ProcessBuilder
。因此,如果你的子流程相同,则无需一遍又一遍地进行此设置。
对于需要为单元测试设置特定环境值的场景,你可能会发现以下技巧很有用。它会在整个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);
}
}
}
}