Programing

Java에서 환경 변수를 설정하는 방법

lottogame 2020. 3. 29. 08:41
반응형

Java에서 환경 변수를 설정하는 방법


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시작하기 전에 s를 통과하십시오 .

또한 이미 알고있을 수도 있지만 같은로 여러 프로세스를 시작할 수 있습니다 ProcessBuilder. 따라서 하위 프로세스가 동일하면이 설정을 반복해서 수행 할 필요가 없습니다.


단위 테스트를 위해 특정 환경 값을 설정해야하는 시나리오에서 사용하려면 다음 해킹이 유용 할 수 있습니다. JVM 전체에서 환경 변수가 변경되므로 테스트 후 변경 사항을 다시 설정해야하지만 시스템 환경은 변경되지 않습니다.

나는 에드워드 캠벨 (Edward Campbell)의 두 가지 더러운 해킹과 익명의 조합이 가장 잘 작동한다는 것을 알았습니다. 하나는 리눅스에서 작동하지 않고 하나는 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);
      }
    }
  }
}

이것은 매력처럼 작동합니다. 이 핵의 두 저자에게 완전한 크레딧.


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);
  }

// 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);
}

안드로이드에서 인터페이스는 일종의 숨겨진 API로 Libcore.os를 통해 노출됩니다.

Libcore.os.setenv("VAR", "value", bOverwrite);
Libcore.os.getenv("VAR"));

인터페이스 OS뿐만 아니라 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;
}

리눅스 만

단일 환경 변수 설정 (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);
    }
}

용법:

먼저 원하는 클래스 (예 : SystemUtil)에 메소드를 넣습니다.

SystemUtil.setEnv("SHELL", "/bin/bash");

System.getenv("SHELL")이 후에 전화 하면 "/bin/bash"다시 돌아옵니다.


@ pushy / @ anonymous / @ Edward Campbell의 솔루션은 Android가 실제로 Java가 아니기 때문에 Android에서 작동하지 않는 것으로 나타났습니다. 특히 Android에는 전혀 없습니다 java.lang.ProcessEnvironment. 그러나 안드로이드에서는 더 쉽다는 것이 밝혀졌습니다 setenv(). POSIX에 대한 JNI 호출 만하면됩니다 .

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;
}

그리고 자바에서 :

public class Posix {

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

    private void runTest() {
        Posix.setenv("LD_LIBRARY_PATH", "foo", true);
    }
}

이것은 자바로 변환 된 @ paul-blair의 답변과 paul blair가 지적한 정리 및 @Edward Campbell으로 구성된 @pushy 코드 내부에있는 것으로 보이는 일부 실수와 익명을 포함하는 조합입니다.

나는이 코드가 테스트에 얼마나 사용되어야하는지 강조 할 수 없으며 매우 해킹 적이다. 그러나 테스트에서 환경 설정이 필요한 경우 정확히 필요합니다.

여기에는 코드가 작동하는 두 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)

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)

구현 :

/**
 * 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));
}

온라인으로 돌아 다니면 JNI 로이 작업을 수행하는 것이 가능할 것 같습니다. 그런 다음 C에서 putenv ()를 호출해야하며 아마도 Windows와 UNIX에서 모두 작동하는 방식으로 수행해야합니다.

모든 것이 가능하다면, 자바가 저를 똑 바른 재킷에 넣는 대신 이것을 지원하기가 너무 어렵지 않을 것입니다.

다른 곳에서 Perl을 사용하는 친구는 환경 변수가 전역 적으로 처리되고 Java가 우수한 디자인을위한 우수한 격리를 위해 노력하고 있기 때문이라고 제안합니다.


위의 pushy의 답변을 시험해 보았으며 대부분 효과가있었습니다. 그러나 특정 상황 에서이 예외가 표시됩니다.

java.lang.String cannot be cast to java.lang.ProcessEnvironment$Variable

밖이 회전은 특정 내부 클래스의 구현 때문에, 메소드가 한 번 이상 호출 될 때 일어날 ProcessEnvironment.경우 setEnv(..)키가에서 검색하는 방법은 두 번 이상이라고, theEnvironment지도, 그들에 넣어 된 문자열은 (지금 의 첫 번째 호출하여 문자열로 setEnv(...)) 및지도의 제네릭 형식에 캐스트 할 수없는 Variable,의 개인 내부 클래스입니다ProcessEnvironment.

고정 버전 (스칼라)은 다음과 같습니다. 바라건대 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()
  }
}

이 스레드를 찾은 대부분의 사람들과 마찬가지로, 몇 가지 단위 테스트를 작성하고 테스트를 실행하기위한 올바른 조건을 설정하기 위해 환경 변수를 수정해야했습니다. 그러나 가장 많이 찬란한 답변에는 몇 가지 문제가 있거나 매우 복잡하거나 지나치게 복잡하다는 것을 알았습니다. 잘하면 이것은 다른 사람들이 솔루션을 더 빨리 분류하는 데 도움이 될 것입니다.

먼저 @Hubert Grzeskowiak의 솔루션이 가장 간단하다는 것을 알았습니다. 나는 그 중 하나에 먼저 왔으면 좋겠다. @Edward Campbell의 답변을 기반으로하지만 루프 검색이 복잡하지 않습니다.

그러나 @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를 사용하여 데이터 구조에서 후속 조작이 조작 될 때 잠재적으로 문제점이 발생합니다. 또한 개별 요소에 액세스 / 제거하는 것이 문제입니다. 해결책은 '수정 불가능한 환경'을 통해 '환경'에 간접적으로 액세스하는 것입니다. 그러나 이것은 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);
}

이것은 @pushy의 사악한 답변 의 Kotlin 사악한 버전입니다 =)

@Suppress("UNCHECKED_CAST")
@Throws(Exception::class)
fun setEnv(newenv: Map<String, String>) {
    try {
        val processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment")
        val theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment")
        theEnvironmentField.isAccessible = true
        val env = theEnvironmentField.get(null) as MutableMap<String, String>
        env.putAll(newenv)
        val theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment")
        theCaseInsensitiveEnvironmentField.isAccessible = true
        val cienv = theCaseInsensitiveEnvironmentField.get(null) as MutableMap<String, String>
        cienv.putAll(newenv)
    } catch (e: NoSuchFieldException) {
        val classes = Collections::class.java.getDeclaredClasses()
        val env = System.getenv()
        for (cl in classes) {
            if ("java.util.Collections\$UnmodifiableMap" == cl.getName()) {
                val field = cl.getDeclaredField("m")
                field.setAccessible(true)
                val obj = field.get(env)
                val map = obj as MutableMap<String, String>
                map.clear()
                map.putAll(newenv)
            }
        }
    }

적어도 macOS Mojave에서 작동합니다.


SpringBoot로 작업하는 경우 다음 특성에서 환경 변수를 지정하여 추가 할 수 있습니다.

was.app.config.properties.toSystemProperties

내가 최근 Edward의 답변을 기반으로 한 Kotlin 구현 :

fun setEnv(newEnv: Map<String, String>) {
    val unmodifiableMapClass = Collections.unmodifiableMap<Any, Any>(mapOf()).javaClass
    with(unmodifiableMapClass.getDeclaredField("m")) {
        isAccessible = true
        @Suppress("UNCHECKED_CAST")
        get(System.getenv()) as MutableMap<String, String>
    }.apply {
        clear()
        putAll(newEnv)
    }
}

-D를 사용하여 초기 Java 프로세스에 매개 변수를 전달할 수 있습니다.

java -cp <classpath> -Dkey1=value -Dkey2=value ...

참고 URL : https://stackoverflow.com/questions/318239/how-do-i-set-environment-variables-from-java

반응형