392 votes

Comment définir les variables d'environnement à partir de Java ?

Comment définir les variables d'environnement à partir de Java ? Je vois que je peux le faire pour les sous-processus à l'aide des éléments suivants ProcessBuilder . Mais comme j'ai plusieurs sous-processus à lancer, je préfère modifier l'environnement du processus actuel et laisser les sous-processus en hériter.

Il y a un System.getenv(String) pour obtenir une seule variable d'environnement. Je peux également obtenir une Map de l'ensemble complet des variables d'environnement avec System.getenv() . Mais, en appelant put() sur ce point Map lance un UnsupportedOperationException -- apparemment, ils veulent que l'environnement soit en lecture seule. Et, il n'y a pas de System.setenv() .

Existe-t-il un moyen de définir des variables d'environnement dans le processus en cours d'exécution ? Si oui, comment ? Si non, quel est le raisonnement ? (Est-ce parce que c'est Java et donc que je ne devrais pas faire des choses obsolètes non portables comme toucher à mon environnement) ? Et sinon, avez-vous de bonnes suggestions pour gérer les changements de variables d'environnement que je vais devoir transmettre à plusieurs sous-processus ?

1 votes

System.getEnv() est destiné à être universel, certains environnements n'ont même pas de variables d'environnement.

17 votes

Pour tous ceux qui en ont eu besoin dans le cadre de tests unitaires : stackoverflow.com/questions/8168884/

1 votes

0voto

Keith K Points 1

jython variante basée sur @pushy's réponse, fonctionne sous Windows.

def set_env(newenv):
    from java.lang import Class
    process_environment = Class.forName("java.lang.ProcessEnvironment")
    environment_field =  process_environment.getDeclaredField("theEnvironment")
    environment_field.setAccessible(True)
    env = environment_field.get(None)
    env.putAll(newenv)
    invariant_environment_field = process_environment.getDeclaredField("theCaseInsensitiveEnvironment");
    invariant_environment_field.setAccessible(True)
    invevn = invariant_environment_field.get(None)
    invevn.putAll(newenv)

Utilisation :

old_environ = dict(os.environ)
old_environ['EPM_ORACLE_HOME'] = r"E:\Oracle\Middleware\EPMSystem11R1"
set_env(old_environ)

0voto

Tiarê Balbi Points 1003

Une version en Kotlin, dans cet algorithme j'ai créé un décorateur qui permet de définir et de récupérer des variables de l'environnement.

import java.util.Collections
import kotlin.reflect.KProperty

class EnvironmentDelegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return System.getenv(property.name) ?: "-"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        val key = property.name

        val classes: Array<Class<*>> = Collections::class.java.declaredClasses
        val env = System.getenv()

        val cl = classes.first { "java.util.Collections\$UnmodifiableMap" == it.name }

        val field = cl.getDeclaredField("m")
        field.isAccessible = true
        val obj = field[env]
        val map = obj as MutableMap<String, String>
        map.putAll(mapOf(key to value))
    }
}

class KnownProperties {
    var JAVA_HOME: String by EnvironmentDelegate()
    var sample: String by EnvironmentDelegate()
}

fun main() {
    val knowProps = KnownProperties()
    knowProps.sample = "2"

    println("Java Home: ${knowProps.JAVA_HOME}")
    println("Sample: ${knowProps.sample}")
}

-2voto

Rik Points 354

Mise en œuvre de Kotlin que j'ai récemment réalisée sur la base de la réponse d'Edward :

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

-2voto

anarinsky Points 668

Si vous travaillez avec SpringBoot, vous pouvez ajouter la spécification de la variable environnementale dans la propriété suivante :

was.app.config.properties.toSystemProperties

-16voto

matt b Points 73770

Vous pouvez passer des paramètres dans votre processus java initial avec -D :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X