web-dev-qa-db-fra.com

Est-il possible de définir une variable d'environnement à l'exécution à partir de Java?

Est-il possible de définir une variable d'environnement au moment de l'exécution à partir d'une application Java? Dans la classe Java 1.5 Java.lang.System, il existe une méthode getenv (); je n'aurais besoin que d'une méthode setenv () ...

Est-il possible de modifier les variables d'environnement dans le processus Java lui-même? pas dans le processus enfant.

Est-il possible d'y parvenir grâce à JNI? Et comment cela fonctionnerait-il?

Merci.

EDIT: .__ Ok. Permettez-moi de formuler les choses comme suit: pouvons-nous faire ce qui suit avec Java? Répondre s'il vous plaît.

  1. Peut-on modifier l'environnement du processus en cours?
  2. Peut-on modifier l'environnement du processus parent?
  3. Peut-on modifier l'environnement du processus enfant?

Hemal Pandya a répondu: "Vous pouvez modifier l'environnement des processus en cours et des processus enfants, mais pas du processus parent qui a généré ce processus." Es-tu d'accord avec ça ?

36
Vicky

Si mon intuition est correcte et que vous souhaitez réellement modifier l'environnement au profit d'un sous-processus spawned (forked) (Runtime.getRuntime().exec()), utilisez ProcessBuilder au lieu de exec(). Vous pouvez créer un environnement personnalisé via la méthode environment () de votre instance ProcessBuilder.

Si c’est pas ce que vous essayez d’atteindre, veuillez ignorer cette réponse.


METTRE À JOUR

La réponse à vos trois questions spécifiques mises à jour est la suivante:

  1. Peut-on modifier l'environnement du processus en cours?
    • Pas facilement. Cela dépend si vous souhaitez modifier l'environnement du processus, les valeurs renvoyées par System.getenv() dans la même machine virtuelle, ou les deux.
    • Comme Greg Hewgill l'a souligné, pour modifier l'environnement du processus actuel, vous pouvez appeler setenv ou son équivalent spécifique à la plate-forme via JNI. Vous pouvez également utiliser la méthode extrêmement compliquée de point 2 ci-dessous, qui fonctionne pour tout processus (à condition que vous disposiez des autorisations). Sachez toutefois que dans la plupart des machines virtuelles, cette modification peut ne jamais être reflétée dans les valeurs renvoyées par System.getenv(). , car l’environnement est le plus souvent mis en cache au démarrage de la machine virtuelle dans un Java.util.Map (ou l’équivalent).
    • Pour changer la copie en cache de l'environnement de la machine virtuelle Java, lorsqu'un cache est utilisé (voir le code source dans System.Java dans la distribution que vous utiliserez pour le déploiement de la machine virtuelle Java), vous pouvez essayer de pirater l'implémentation (via l'ordre de chargement des classes, réflexion)). ou (instrumentation } _.) Dans le cas de la machine virtuelle Java v1.6 de Sun, par exemple, le cache d'environnement est géré par la classe non documentée ProcessEnvironment (que vous pouvez corriger).
  2. Pouvons-nous modifier l'environnement du processus parent?
  3. Pouvons-nous modifier l'environnement du processus enfant?
    • Oui, via ProcessBuilder lors de la génération du processus.
    • Si le processus a déjà été créé lorsque l'altération de l'environnement est requise, vous devez utiliser la méthode méthode 2 ci-dessus (ou une méthode également compliquée, telle que l'injection de code au moment de la génération, contrôlée ultérieurement par le biais du processus parent, par exemple.

Notez que toutes les méthodes ci-dessus, à l'exception de celle impliquant ProcessBuilder, sont fragiles, sujettes aux erreurs, non portables à des degrés divers et sujettes aux conditions de concurrence dans des environnements multithreads.

34
vladr

En réponse à votre question mise à jour:

  1. Peut-on modifier l'environnement du processus en cours?
    Oui , si vous utilisez JNI pour appeler setenv() ou autre chose. Cependant, vous n’avez probablement pas besoin de le faire et cela peut ne pas fonctionner dans toutes les situations.
  2. Peut-on modifier l'environnement du processus parent?
    Non .
  3. Peut-on modifier l'environnement du processus enfant?
    Oui , en utilisant ProcessBuilder.
6
Greg Hewgill

Vous pouvez obtenir un descripteur de la carte sous-jacente sur laquelle ProcessEnvironment se tient, puis mettre de nouvelles choses et supprimer toutes celles que vous voulez. 

Cela fonctionne sur Java 1.8.0_144. Je ne peux pas garantir que cela fonctionne sur n'importe quelle version de Java, mais c'est probablement similaire si vous devez vraiment changer l'environnement au moment de l'exécution.

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

Après avoir obtenu la référence à la carte, ajoutez ce que vous voulez et récupérez-la à l'aide de l'ancien appel System.getenv ("") habituel.

J'ai essayé cela fonctionne dans MAC ne fonctionne pas dans Windows dans les deux versions Java Java 1.8_161 

4
Narcoleptic Snowman

Je ne pense pas, du moins pas uniquement en Java, mais pourquoi avez-vous besoin de faire cela? En Java, il est préférable d’utiliser des propriétés via System.getProperties(), que vous pouvez modifier.

Si vous en aviez vraiment besoin, je suis sûr que vous pourriez insérer la fonction C setenv dans un appel JNI. En fait, je ne serais pas surpris que quelqu'un l'ait déjà fait. Je ne connais pas les détails du code, cependant.

1
David Z

Vous pouvez modifier l'environnement des processus en cours et des processus enfants, mais pas du processus parent ayant généré ce processus. 

0
Miserable Variable