如何从Java中设置环境变量?我发现我可以使用ProcessBuilder为子流程做到这一点。不过,我有几个子流程要启动,所以我宁愿修改当前流程的环境,让子流程继承它。
有一个System.getenv(String)用于获取单个环境变量。我还可以使用System.getenv()获得完整环境变量集的Map。但是,在该Map上调用put()会抛出UnsupportedOperationException——显然,它们意味着环境是只读的。并且,没有System.setenv()。
那么,有没有办法在当前运行的进程中设置环境变量呢?如果有,怎么做?如果不是,理由是什么?(是不是因为这是Java,所以我不应该做邪恶的、不可移植的、过时的事情,比如触摸我的环境?)如果不是,有什么好的建议来管理我将需要提供给几个子流程的环境变量更改吗?
(是不是因为这是Java,所以我不应该做邪恶的、不可移植的、过时的事情,比如触摸我的环境?)
我认为你说到点子上了。
减轻负担的一个可能的方法是找出一种方法
void setUpEnvironment(ProcessBuilder builder) {
Map<String, String> env = builder.environment();
// blah blah
}
并在启动任何processbuilder之前通过它。
另外,您可能已经知道这一点,但是您可以使用同一个ProcessBuilder启动多个流程。因此,如果子流程是相同的,就不需要一遍又一遍地进行这个设置。
在Android上,界面是通过Libcore公开的。os作为一种隐藏的API。
Libcore.os.setenv("VAR", "value", bOverwrite);
Libcore.os.getenv("VAR"));
Libcore类和接口操作系统都是公开的。只有类声明缺失,需要显示给链接器。不需要将类添加到应用程序中,但是如果包含了类也无妨。
package libcore.io;
public final class Libcore {
private Libcore() { }
public static Os os;
}
package libcore.io;
public interface Os {
public String getenv(String name);
public void setenv(String name, String value, boolean overwrite) throws ErrnoException;
}
只需使用反射,比如setEnv("k1","v1")
private void setEnv(String key, String val) throws Exception {
getModifiableEnv().put(key, val);
}
private Map<String, String> getModifiableEnv() throws Exception {
Map<String, String> unmodifiableEnv = System.getenv();
Field field = unmodifiableEnv.getClass().getDeclaredField("m");
field.setAccessible(true);
return (Map<String, String>) field.get(unmodifiableEnv);
}
need
import java.lang.reflect.Field;
import java.util.Map;
public static void set(Map<String, String> newenv) throws Exception {
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);
}
}
}
或者根据joshwolfe的建议添加/更新一个单独的var并删除循环。
@SuppressWarnings({ "unchecked" })
public static void updateEnv(String name, String val) throws ReflectiveOperationException {
Map<String, String> env = System.getenv();
Field field = env.getClass().getDeclaredField("m");
field.setAccessible(true);
((Map<String, String>) field.get(env)).put(name, val);
}