是否可以在运行时从 Java 设置环境变量?

2022-08-31 19:37:07

是否可以在运行时从 Java 应用程序设置环境变量?在Java 1.5 java.lang.System类中有getenv()方法,我只需要一个setenv()方法...

是否可以修改java进程本身中的环境变量;不在子进程中。

是否有可能通过JNI实现它?这又如何运作呢?

谢谢。

编辑:好吧,让我这样说 - 我们可以用Java做以下事情吗?请回答。

  1. 我们可以修改当前进程的环境吗?
  2. 我们可以修改父进程的环境吗?
  3. 我们可以修改子进程的环境吗?

Hemal Pandya回答说:“您可以修改当前进程和子进程的环境,但不能修改生成该进程的父进程的环境。你同意这个观点吗?


答案 1

如果我的直觉是正确的,并且您实际上想要修改环境以有利于生成(分叉)子进程(),那么请使用ProcessBuilder而不是。您可以通过实例的 environment() 方法构建自定义环境。Runtime.getRuntime().exec()exec()ProcessBuilder

如果这不是你想要达到的目标,那么请忽略这个答案。


更新

您更新的三个具体问题的答案如下:

  1. 我们可以修改当前进程的环境吗?
    • 不容易。取决于您是要更改进程的环境、更改 同一 JVM 中返回的值,还是同时更改两者。System.getenv()
    • 正如Greg Hewgill所指出的,要改变当前流程的环境,你可以通过JNI调用它或它特定于平台的等价物。您也可以使用下面第2点中极其复杂的方法,该方法适用于任何进程(前提是您具有权限)。但是,请注意,在大多数 JVM 中,此更改可能永远不会反映在 返回的值中,因为环境通常在虚拟机启动时缓存在 (或等效项) 中。setenvSystem.getenv()java.util.Map
    • 要更改环境的 JVM 缓存副本,在使用缓存时(请参阅您将用于部署的任何 JVM 发行版中的源代码),您可以尝试破解实现(通过类加载顺序、反射检测)。例如,对于 SUN 的 v1.6 JVM,环境缓存由未记录的类(您可以修补)管理。System.javaProcessEnvironment
  2. 我们可以修改父进程的环境吗?
  3. 我们可以修改子进程的环境吗?
    • 是的,通过生成进程时。ProcessBuilder
    • 如果在需要环境更改时已经生成了进程,则需要上述方法2(或者一些同样复杂的方法,例如在生成时注入代码,通过例如由父进程的套接字进行不可告人地控制。

请注意,上述所有方法(涉及的方法除外)都是脆的、容易出错的、不同程度的不可移植性,并且容易在多线程环境中出现争用条件。ProcessBuilder


答案 2

你可以在底层地图上得到一个手柄,然后放新的东西,并删除你想要的东西。java.lang.ProcessEnvironment

这适用于java 1.8.0_144。不能保证它适用于任何其他版本的java,但是如果您确实需要在运行时更改环境,则可能类似。

private static Map<String,String> getModifiableEnvironment() throws Exception{
    Class pe = Class.forName("java.lang.ProcessEnvironment");
    Method getenv = pe.getDeclaredMethod("getenv");
    getenv.setAccessible(true);
    Object unmodifiableEnvironment = getenv.invoke(null);
    Class map = Class.forName("java.util.Collections$UnmodifiableMap");
    Field m = map.getDeclaredField("m");
    m.setAccessible(true);
    return (Map) m.get(unmodifiableEnvironment);
}

获取对地图的引用后,只需添加所需的任何内容,现在就可以使用常规的旧调用来检索它。System.getenv("")

我试过这个它在MAC中工作,在Windows中不起作用,在两个操作系统Java版本1.8_161中都不起作用


推荐