当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《是否可以在运行时从Java设置环境变量?》经验,为你挑选了3个好方法。

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

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

是否有可能通过JNI实现它?那会怎么样?

谢谢.

编辑:好的,让我这样说吧 - 我们可以用Java做以下几点.请回答.

    我们可以修改当前流程的环境吗?

    我们可以修改父进程的环境吗?

    我们可以修改子进程的环境吗?

Hemal Pandya回答说:"您可以修改当前和子进程的环境,但不能修改产生此进程的父进程的环境." 你同意吗?



1> vladr..:

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

如果这不是你想要达到的目的,那么请不要理会这个答案.


UPDATE

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

    我们可以修改当前流程的环境吗?

    不容易.取决于您是否要更改进程的环境,更改System.getenv()同一JVM中返回的值,或两者.

    正如Greg Hewgill指出的那样,要改变当前流程的环境,您可以setenv通过JNI 调用它或其特定于平台的等价物.您也可以使用下面第2点中极其复杂的方法,该方法适用于任何进程(前提是您拥有权限.)但是,请注意,在大多数JVM中,此更改可能永远不会反映在返回的值中System.getenv(),因为环境是通常在java.util.Map(或等效的)虚拟机启动时缓存.

    要更改JVM的缓存环境副本,在使用缓存时(请参阅System.java将用于部署的JVM分发中的源代码),您可以尝试破解实现(通过类加载顺序,反射或检测.例如,对于SUN的v1.6 JVM,环境缓存由未记录的ProcessEnvironment类(可以修补)管理.

    我们可以修改父进程的环境吗?

    非常困难,非常便携.如果您绝对必须遵守,那么您可以使用非常具体的黑客攻击:

    Windows:动态添加/编辑远程进程的环境变量

    *nix:有没有办法改变另一个进程的环境变量?- 这是一个性能杀手,因为所检测的任何过程gdb都将暂停非零时间.

    我们可以修改子进程的环境吗?

    是的,通过ProcessBuilder产生过程.

    如果在需要进行环境更改时已经生成了该进程,则需要上面的方法2(或者某些同样复杂的方法,例如在生成时的代码注入,通过父进程通过例​​如套接字进行进一步控制).

请注意,除了涉及的方法之外,上述所有方法ProcessBuilder都是脆弱的,容易出错,在不同程度上不可移植,并且在多线程环境中容易出现竞争条件.



2> Greg Hewgill..:

回答您的更新问题:

    我们可以修改当前流程的环境吗?
    是的,如果您使用JNI打电话setenv()或其他什么.你可能不需要这样做,它可能不适用于所有情况.

    我们可以修改父进程的环境吗?
    .

    我们可以修改子进程的环境吗?
    是的,使用ProcessBuilder.



3> 小智..:

您可以在ProcessEnvironment所坚持的基础地图上获得一个句柄,然后放置新的东西并删除所有想要的东西。

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

private static Map 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 OS的两个OS版本1.8_161中都无法在MAC中工作

推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有