如何从Java设置环境变量?

ski*_*ppy 270 java environment-variables

如何从Java设置环境变量?我看到我可以使用子进程执行此操作ProcessBuilder.我有几个子进程要启动,所以我宁愿修改当前进程的环境,让子进程继承它.

有一个System.getenv(String)获取单个环境变量.我也可以获得一套Map完整的环境变量System.getenv().但是,要求put()Map引发UnsupportedOperationException-显然,他们的意思是对环境只能被读取.并且,没有System.setenv().

那么,有没有办法在当前运行的进程中设置环境变量?如果是这样,怎么样?如果没有,理由是什么?(这是因为这是Java,因此我不应该做一些邪恶的非便携式过时的事情,比如触摸我的环境吗?)如果没有,那么管理环境变量的任何好建议都会改变我需要提供给几个子进程?

pus*_*shy 220

要在需要为单元测试设置特定环境值的场景中使用,您可能会发现以下hack非常有用.它将更改整个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);
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这个作品就像一个魅力.对这些黑客的两位作者的完全信任.

  • 这只会改变内存中的环境变量.这对测试很有用,因为您可以根据测试需要设置环境变量,但将envs保留在系统中.事实上,我强烈反对任何人将此代码用于除测试之外的任何其他目的.这段代码很邪恶;-) (33认同)
  • 作为FYI,JVM在启动时创建环境变量的副本.这将编辑该副本,而不是编辑启动JVM的父进程的环境变量. (8认同)
  • 当然,`import java.lang.reflect.Field;` (5认同)
  • 这只会改变内存,还是实际上改变系统中的整个环境变量? (2认同)
  • 该方法不起作用,ProcessEnvironment在jdk8中没有CaseInsensitiveEnvironment字段! (2认同)
  • 在 OpenJDK 17 中不起作用。并且 Linux 和 Windows 的相应实现有所不同。 (2认同)

Mic*_*ers 85

(这是因为这是Java,因此我不应该做一些邪恶的非便携式过时的东西,比如触摸我的环境吗?)

我觉得你已经敲了敲头.

减轻负担的一种可能方法是分解出一种方法

void setUpEnvironment(ProcessBuilder builder) {
    Map<String, String> env = builder.environment();
    // blah blah
}
Run Code Online (Sandbox Code Playgroud)

ProcessBuilder在启动之前传递任何s.

此外,您可能已经知道这一点,但您可以使用相同的方法启动多个进程ProcessBuilder.因此,如果您的子流程相同,则无需反复进行此设置.

  • @ b1naryatr0phy你错过了这一点.没有人可以使用*您的环境变量*因为这些变量是进程的本地变量(您在Windows中设置的是默认值).每个进程都可以自由更改自己的变量......除非是Java. (22认同)
  • S.Lott,我不打算设置父母的环境.我想设置自己的环境. (17认同)
  • java的这种限制是一个小问题.java没有理由不让你设置env vars而不是"因为我们不希望java这样做". (7认同)
  • 这很有效,除非是其他人的库(例如Sun的)正在启动这个过程. (3认同)

小智 57

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这不会更改系统上的环境变量,但会在当前的Java调用中更改它们.这对于单元测试非常有用. (11认同)
  • 它在 java17 上停止工作 (9认同)
  • 为什么不使用`Class <?> cl = env.getClass();`而不是for循环? (8认同)
  • 听起来这会修改内存中的地图,但是它会将值保存到系统中吗? (3认同)

小智 18

// this is a dirty hack - but should be ok for a unittest.
private void setNewEnvironmentHack(Map<String, String> newenv) throws Exception
{
  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.clear();
  env.putAll(newenv);
  Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
  theCaseInsensitiveEnvironmentField.setAccessible(true);
  Map<String, String> cienv = (Map<String, String>) theCaseInsensitiveEnvironmentField.get(null);
  cienv.clear();
  cienv.putAll(newenv);
}
Run Code Online (Sandbox Code Playgroud)


小智 16

在Android上,该接口通过Libcore.os作为一种隐藏的API公开.

Libcore.os.setenv("VAR", "value", bOverwrite);
Libcore.os.getenv("VAR"));
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

  • API 21现在有'Os.setEnv`.http://developer.android.com/reference/android/system/Os.html#setenv(java.lang.String,java.lang.String,boolean) (7认同)

Hub*_*iak 11

仅限Linux

设置单个环境变量(基于Edward Campbell的回答):

public static void setEnv(String key, String value) {
    try {
        Map<String, String> env = System.getenv();
        Class<?> cl = env.getClass();
        Field field = cl.getDeclaredField("m");
        field.setAccessible(true);
        Map<String, String> writableEnv = (Map<String, String>) field.get(env);
        writableEnv.put(key, value);
    } catch (Exception e) {
        throw new IllegalStateException("Failed to set environment variable", e);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

首先,将该方法放在您想要的任何类中,例如SystemUtil.

SystemUtil.setEnv("SHELL", "/bin/bash");
Run Code Online (Sandbox Code Playgroud)

如果你System.getenv("SHELL")在此之后打电话,你会"/bin/bash"回来的.

  • 它在 java17 上停止工作 (4认同)

Ash*_*eze 9

有三个库可以在单元测试期间执行此操作。

Stefan Birkner 的系统规则和系统 Lambda - https://www.baeldung.com/java-system-rules-junit允许您执行以下操作:

public class JUnitTest {

    @Rule
    public EnvironmentVariables environmentVariables = new EnvironmentVariables();

    @Test
    public void someTest() {
        environmentVariables.set("SOME_VARIABLE", "myValue");
        
        // now System.getenv does what you want
    }
}
Run Code Online (Sandbox Code Playgroud)

或者对于系统-Lambda:

@Test
void execute_code_with_environment_variables(
) throws Exception {
  List<String> values = withEnvironmentVariable("first", "first value")
    .and("second", "second value")
    .execute(() -> asList(
      System.getenv("first"),
      System.getenv("second")
    ));
  assertEquals(
    asList("first value", "second value"),
    values
  );
}
Run Code Online (Sandbox Code Playgroud)

上述功能也可通过系统存根作为 JUnit 5 扩展使用:

@ExtendWith(SystemStubsExtension.class)
class SomeTest {

    @SystemStub
    private EnvironmentVariables;

    @Test
    void theTest() {
        environmentVariables.set("SOME_VARIABLE", "myValue");
        
        // now System.getenv does what you want

    }

}
Run Code Online (Sandbox Code Playgroud)

系统存根向后兼容系统 Lambda 和系统规则,但支持 JUnit 5。

或者,还有 JUnit Pioneer - https://github.com/junit-pioneer/junit-pioneer,它允许在测试时通过注释设置环境变量。


Pau*_*air 8

尝试了上面的 Pushy 答案,它在很大程度上有效。但是,在某些情况下,我会看到此异常:

java.lang.String cannot be cast to java.lang.ProcessEnvironment$Variable
Run Code Online (Sandbox Code Playgroud)

事实证明,当该方法被多次调用时,由于某些内部类的实现,ProcessEnvironment.如果setEnv(..)多次调用该方法,当从映射中检索键时theEnvironment,它们现在是字符串(已放入第一次调用setEnv(...)) 时作为字符串,并且不能转换为映射的泛型类型,Variable,这是 的私有内部类ProcessEnvironment.

下面是一个固定版本(在 Scala 中)。希望将其移植到 Java 中不会太困难。

def setEnv(newenv: java.util.Map[String, String]): Unit = {
  try {
    val processEnvironmentClass = JavaClass.forName("java.lang.ProcessEnvironment")
    val theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment")
    theEnvironmentField.setAccessible(true)

    val variableClass = JavaClass.forName("java.lang.ProcessEnvironment$Variable")
    val convertToVariable = variableClass.getMethod("valueOf", classOf[java.lang.String])
    convertToVariable.setAccessible(true)

    val valueClass = JavaClass.forName("java.lang.ProcessEnvironment$Value")
    val convertToValue = valueClass.getMethod("valueOf", classOf[java.lang.String])
    convertToValue.setAccessible(true)

    val sampleVariable = convertToVariable.invoke(null, "")
    val sampleValue = convertToValue.invoke(null, "")
    val env = theEnvironmentField.get(null).asInstanceOf[java.util.Map[sampleVariable.type, sampleValue.type]]
    newenv.foreach { case (k, v) => {
        val variable = convertToVariable.invoke(null, k).asInstanceOf[sampleVariable.type]
        val value = convertToValue.invoke(null, v).asInstanceOf[sampleValue.type]
        env.put(variable, value)
      }
    }

    val theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment")
    theCaseInsensitiveEnvironmentField.setAccessible(true)
    val cienv = theCaseInsensitiveEnvironmentField.get(null).asInstanceOf[java.util.Map[String, String]]
    cienv.putAll(newenv);
  }
  catch {
    case e : NoSuchFieldException => {
      try {
        val classes = classOf[java.util.Collections].getDeclaredClasses
        val env = System.getenv()
        classes foreach (cl => {
          if("java.util.Collections$UnmodifiableMap" == cl.getName) {
            val field = cl.getDeclaredField("m")
            field.setAccessible(true)
            val map = field.get(env).asInstanceOf[java.util.Map[String, String]]
            // map.clear() // Not sure why this was in the code. It means we need to set all required environment variables.
            map.putAll(newenv)
          }
        })
      } catch {
        case e2: Exception => e2.printStackTrace()
      }
    }
    case e1: Exception => e1.printStackTrace()
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 即使对于相同的构建,java.lang.ProcessEnvironment 的实现在不同平台上也是不同的。例如,Windows 的实现中没有类 java.lang.ProcessEnvironment$Variable,但 Linux 的实现中存在该类。您可以轻松检查它。只需下载适用于 Linux 的 tar.gz JDK 发行版并从 src.zip 中提取源代码,然后将其与适用于 Windows 的发行版中的相同文件进行比较。它们在 JDK 1.8.0_181 中完全不同。我没有在 Java 10 中检查过它们,但如果有相同的图片我不会感到惊讶。 (2认同)

ded*_*ddu 8

如果您像我一样在测试中遇到这个问题,并且您正在使用 Junit5,Junit-pioneer附带了非常有用的注释。行家发布

例子:

@Test
@SetEnvironmentVariable(key = "some variable",value = "new value")
void test() {
    assertThat(System.getenv("some variable")).
        isEqualTo("new value");
}

Run Code Online (Sandbox Code Playgroud)

强烈推荐它。


Han*_*ner 7

事实证明来自@ pushy/@ anonymous/@ Edward Campbell的解决方案在Android上不起作用,因为Android不是真正的Java.具体来说,Android根本没有java.lang.ProcessEnvironment.但事实证明在Android中更容易,你只需要对POSIX进行JNI调用setenv():

在C/JNI中:

JNIEXPORT jint JNICALL Java_com_example_posixtest_Posix_setenv
  (JNIEnv* env, jclass clazz, jstring key, jstring value, jboolean overwrite)
{
    char* k = (char *) (*env)->GetStringUTFChars(env, key, NULL);
    char* v = (char *) (*env)->GetStringUTFChars(env, value, NULL);
    int err = setenv(k, v, overwrite);
    (*env)->ReleaseStringUTFChars(env, key, k);
    (*env)->ReleaseStringUTFChars(env, value, v);
    return err;
}
Run Code Online (Sandbox Code Playgroud)

在Java中:

public class Posix {

    public static native int setenv(String key, String value, boolean overwrite);

    private void runTest() {
        Posix.setenv("LD_LIBRARY_PATH", "foo", true);
    }
}
Run Code Online (Sandbox Code Playgroud)


Tim*_*yan 7

像大多数发现此线程的人一样,我正在编写一些单元测试,需要修改环境变量以设置正确的测试运行条件。但是,我发现最受好评的答案存在一些问题和/或非常神秘或过于复杂。希望这将帮助其他人更快地理清解决方案。

首先,我终于发现@Hubert Grzeskowiak 的解决方案是最简单的,并且对我有用。我希望我能先来那个。它基于@Edward Campbell 的回答,但没有复杂的 for 循环搜索。

然而,我从@pushy 的解决方案开始,它获得了最多的支持。它是@anonymous 和@Edward Campbell 的组合。@pushy 声称需要这两种方法来覆盖 Linux 和 Windows 环境。我在 OS X 下运行,发现两者都可以工作(一旦@anonymous 方法的问题得到解决)。正如其他人所指出的,此解决方案在大多数情况下都有效,但不是全部。

我认为大部分混乱的根源来自@anonymous 在“环境”领域运行的解决方案。查看ProcessEnvironment结构的定义,'theEnvironment' 不是 Map<String, String>,而是 Map<Variable, Value>。清除地图工作正常,但 putAll 操作将地图重建为 Map<String, String>,当后续操作使用期望 Map<Variable,Value> 的普通 API 对数据结构进行操作时,这可能会导致问题。此外,访问/删除单个元素也是一个问题。解决方案是通过“theUnmodifiableEnvironment”间接访问“theEnvironment”。但由于这是一个类型UnmodifiableMap访问必须通过 UnmodifiableMap 类型的私有变量“m”完成。请参阅下面代码中的 getModifiableEnvironmentMap2。

在我的情况下,我需要为我的测试删除一些环境变量(其他的应该保持不变)。然后我想在测试后将环境变量恢复到之前的状态。下面的例程可以直接做到这一点。我在 OS X 上测试了 getModifiableEnvironmentMap 的两个版本,它们的工作方式相同。尽管基于此线程中的评论,根据环境,一个可能比另一个更好。

注意:我没有包括对“theCaseInsensitiveEnvironmentField”的访问,因为这似乎是特定于 Windows 的,我无法对其进行测试,但添加它应该是直接的。

private Map<String, String> getModifiableEnvironmentMap() {
    try {
        Map<String,String> unmodifiableEnv = System.getenv();
        Class<?> cl = unmodifiableEnv.getClass();
        Field field = cl.getDeclaredField("m");
        field.setAccessible(true);
        Map<String,String> modifiableEnv = (Map<String,String>) field.get(unmodifiableEnv);
        return modifiableEnv;
    } catch(Exception e) {
        throw new RuntimeException("Unable to access writable environment variable map.");
    }
}

private Map<String, String> getModifiableEnvironmentMap2() {
    try {
        Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
        Field theUnmodifiableEnvironmentField = processEnvironmentClass.getDeclaredField("theUnmodifiableEnvironment");
        theUnmodifiableEnvironmentField.setAccessible(true);
        Map<String,String> theUnmodifiableEnvironment = (Map<String,String>)theUnmodifiableEnvironmentField.get(null);

        Class<?> theUnmodifiableEnvironmentClass = theUnmodifiableEnvironment.getClass();
        Field theModifiableEnvField = theUnmodifiableEnvironmentClass.getDeclaredField("m");
        theModifiableEnvField.setAccessible(true);
        Map<String,String> modifiableEnv = (Map<String,String>) theModifiableEnvField.get(theUnmodifiableEnvironment);
        return modifiableEnv;
    } catch(Exception e) {
        throw new RuntimeException("Unable to access writable environment variable map.");
    }
}

private Map<String, String> clearEnvironmentVars(String[] keys) {

    Map<String,String> modifiableEnv = getModifiableEnvironmentMap();

    HashMap<String, String> savedVals = new HashMap<String, String>();

    for(String k : keys) {
        String val = modifiableEnv.remove(k);
        if (val != null) { savedVals.put(k, val); }
    }
    return savedVals;
}

private void setEnvironmentVars(Map<String, String> varMap) {
    getModifiableEnvironmentMap().putAll(varMap);   
}

@Test
public void myTest() {
    String[] keys = { "key1", "key2", "key3" };
    Map<String, String> savedVars = clearEnvironmentVars(keys);

    // do test

    setEnvironmentVars(savedVars);
}
Run Code Online (Sandbox Code Playgroud)


man*_*her 6

这是@ paul-blair转换为Java的答案的组合,其中包括由保罗布莱尔指出的一些清理以及似乎在@pushy的代码内部的一些错误,这些错误由@Edward Campbell和匿名组成.

我不能强调这个代码应该只用于测试多少,而且非常hacky.但是对于需要在测试中设置环境的情况,这正是我所需要的.

这还包括我的一些小修改,允许代码在运行的Windows上运行

java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)
Run Code Online (Sandbox Code Playgroud)

以及运行的Centos

openjdk version "1.8.0_91"
OpenJDK Runtime Environment (build 1.8.0_91-b14)
OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)
Run Code Online (Sandbox Code Playgroud)

实施:

/**
 * Sets an environment variable FOR THE CURRENT RUN OF THE JVM
 * Does not actually modify the system's environment variables,
 *  but rather only the copy of the variables that java has taken,
 *  and hence should only be used for testing purposes!
 * @param key The Name of the variable to set
 * @param value The value of the variable to set
 */
@SuppressWarnings("unchecked")
public static <K,V> void setenv(final String key, final String value) {
    try {
        /// we obtain the actual environment
        final Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
        final Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
        final boolean environmentAccessibility = theEnvironmentField.isAccessible();
        theEnvironmentField.setAccessible(true);

        final Map<K,V> env = (Map<K, V>) theEnvironmentField.get(null);

        if (SystemUtils.IS_OS_WINDOWS) {
            // This is all that is needed on windows running java jdk 1.8.0_92
            if (value == null) {
                env.remove(key);
            } else {
                env.put((K) key, (V) value);
            }
        } else {
            // This is triggered to work on openjdk 1.8.0_91
            // The ProcessEnvironment$Variable is the key of the map
            final Class<K> variableClass = (Class<K>) Class.forName("java.lang.ProcessEnvironment$Variable");
            final Method convertToVariable = variableClass.getMethod("valueOf", String.class);
            final boolean conversionVariableAccessibility = convertToVariable.isAccessible();
            convertToVariable.setAccessible(true);

            // The ProcessEnvironment$Value is the value fo the map
            final Class<V> valueClass = (Class<V>) Class.forName("java.lang.ProcessEnvironment$Value");
            final Method convertToValue = valueClass.getMethod("valueOf", String.class);
            final boolean conversionValueAccessibility = convertToValue.isAccessible();
            convertToValue.setAccessible(true);

            if (value == null) {
                env.remove(convertToVariable.invoke(null, key));
            } else {
                // we place the new value inside the map after conversion so as to
                // avoid class cast exceptions when rerunning this code
                env.put((K) convertToVariable.invoke(null, key), (V) convertToValue.invoke(null, value));

                // reset accessibility to what they were
                convertToValue.setAccessible(conversionValueAccessibility);
                convertToVariable.setAccessible(conversionVariableAccessibility);
            }
        }
        // reset environment accessibility
        theEnvironmentField.setAccessible(environmentAccessibility);

        // we apply the same to the case insensitive environment
        final Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
        final boolean insensitiveAccessibility = theCaseInsensitiveEnvironmentField.isAccessible();
        theCaseInsensitiveEnvironmentField.setAccessible(true);
        // Not entirely sure if this needs to be casted to ProcessEnvironment$Variable and $Value as well
        final Map<String, String> cienv = (Map<String, String>) theCaseInsensitiveEnvironmentField.get(null);
        if (value == null) {
            // remove if null
            cienv.remove(key);
        } else {
            cienv.put(key, value);
        }
        theCaseInsensitiveEnvironmentField.setAccessible(insensitiveAccessibility);
    } catch (final ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
        throw new IllegalStateException("Failed setting environment variable <"+key+"> to <"+value+">", e);
    } catch (final NoSuchFieldException e) {
        // we could not find theEnvironment
        final Map<String, String> env = System.getenv();
        Stream.of(Collections.class.getDeclaredClasses())
                // obtain the declared classes of type $UnmodifiableMap
                .filter(c1 -> "java.util.Collections$UnmodifiableMap".equals(c1.getName()))
                .map(c1 -> {
                    try {
                        return c1.getDeclaredField("m");
                    } catch (final NoSuchFieldException e1) {
                        throw new IllegalStateException("Failed setting environment variable <"+key+"> to <"+value+"> when locating in-class memory map of environment", e1);
                    }
                })
                .forEach(field -> {
                    try {
                        final boolean fieldAccessibility = field.isAccessible();
                        field.setAccessible(true);
                        // we obtain the environment
                        final Map<String, String> map = (Map<String, String>) field.get(env);
                        if (value == null) {
                            // remove if null
                            map.remove(key);
                        } else {
                            map.put(key, value);
                        }
                        // reset accessibility
                        field.setAccessible(fieldAccessibility);
                    } catch (final ConcurrentModificationException e1) {
                        // This may happen if we keep backups of the environment before calling this method
                        // as the map that we kept as a backup may be picked up inside this block.
                        // So we simply skip this attempt and continue adjusting the other maps
                        // To avoid this one should always keep individual keys/value backups not the entire map
                        LOGGER.info("Attempted to modify source map: "+field.getDeclaringClass()+"#"+field.getName(), e1);
                    } catch (final IllegalAccessException e1) {
                        throw new IllegalStateException("Failed setting environment variable <"+key+"> to <"+value+">. Unable to access field!", e1);
                    }
                });
    }
    LOGGER.info("Set environment variable <"+key+"> to <"+value+">. Sanity Check: "+System.getenv(key));
}
Run Code Online (Sandbox Code Playgroud)


ski*_*ppy 5

网上查了一下,好像用JNI可以做到这一点。然后,您必须从 C 调用 putenv(),并且(大概)必须以在 Windows 和 UNIX 上都有效的方式来执行此操作。

如果这一切都能完成,那么 Java 本身支持这一点肯定不会太难,而不是让我陷入困境。

其他地方一位讲 Perl 的朋友表示,这是因为环境变量是进程全局的,而 Java 正在努力实现良好的隔离以实现良好的设计。

  • @Darron 很多人想要这样做的原因与 JVM 认为的环境完全无关。(考虑在调用“Runtime.loadLibrary()”之前设置“LD_LIBRARY_PATH”;它调用的“dlopen()”调用查看的是_real_环境,而不是Java的相同想法)。 (2认同)