web-dev-qa-db-fra.com

Portée des propriétés du système Java

En Java, nous utilisons la méthode System.setProperty () pour définir certaines propriétés du système. Selon cet article , l’utilisation des propriétés du système est un peu délicate.

System.setProperty () peut être un appel maléfique. 

  • C'est 100% thread-hostile
  • Il contient des variables super-globales
  • Il est extrêmement difficile de déboguer lorsque ces variables mystérieusement changer au moment de l'exécution.

Mes questions sont les suivantes.

  1. Comment sur la portée des propriétés du système? Sont-ils spécifiques à chaque machine virtuelle ou ont-ils une nature "super globale" qui partage le même ensemble de propriétés sur chaque instance de machine virtuelle? Je suppose que l'option 1

  2. Existe-t-il des outils pouvant être utilisés pour surveiller les modifications d'exécution afin de détecter les modifications dans les propriétés système. (Juste pour la facilité de détection des problèmes)

Portée des propriétés du système

Au moins après avoir lu les spécifications de l'API pour la méthode System.setProperties , il m'a été impossible d'obtenir une réponse indiquant si les propriétés système sont partagées par toutes les instances de la machine virtuelle Java.

Pour le savoir, j'ai écrit deux programmes rapides qui vont définir la propriété système via System.setProperty, en utilisant la même clé, mais des valeurs différentes:

class T1 {
  public static void main(String[] s) {
    System.setProperty("dummy.property", "42");

    // Keep printing value of "dummy.property" forever.
    while (true) {
      System.out.println(System.getProperty("dummy.property"));
      try {
        Thread.sleep(500);
      } catch (Exception e) {}
    }
  }
}

class T2 {
  public static void main(String[] s) {
    System.setProperty("dummy.property", "52");

    // Keep printing value of "dummy.property" forever.
    while (true) {
      System.out.println(System.getProperty("dummy.property"));
      try {
        Thread.sleep(500);
      } catch (Exception e) {}
    }
  }
}

(Attention, l'exécution des deux programmes ci-dessus les fera passer dans une boucle infinie!)

Il s'avère que lors de l'exécution des deux programmes à l'aide de deux processus Java distincts, la valeur de la propriété définie dans un processus JVM n'affecte pas la valeur de l'autre processus JVM.

Je devrais ajouter que c’est le résultat de l’utilisation de JRE 1.6.0_12 de Sun, et que ce comportement n’est pas défini au moins dans les spécifications de l’API (ou que je n’ai pas pu le trouver), les comportements peuvent varier.

Existe-t-il des outils pour surveiller les modifications d'exécution

Pas à ma connaissance. Toutefois, si vous devez vérifier si les propriétés système ont été modifiées, vous pouvez conserver une copie de la variable Properties à la fois et la comparer à un autre appel de System.getProperties - après tout, Properties est un sous-classe de Hashtable , la comparaison sera donc effectuée de la même manière.

Voici un programme qui montre un moyen de vérifier si les propriétés du système ont été modifiées. Ce n'est probablement pas une méthode élégante, mais il semble faire son travail:

import Java.util.*;

class CheckChanges {

  private static boolean isDifferent(Properties p1, Properties p2) {
    Set<Map.Entry<Object, Object>> p1EntrySet = p1.entrySet();
    Set<Map.Entry<Object, Object>> p2EntrySet = p2.entrySet();

    // Check that the key/value pairs are the same in the entry sets
    // obtained from the two Properties.
    // If there is an difference, return true.
    for (Map.Entry<Object, Object> e : p1EntrySet) {
      if (!p2EntrySet.contains(e))
        return true;
    }
    for (Map.Entry<Object, Object> e : p2EntrySet) {
      if (!p1EntrySet.contains(e))
        return true;
    }

    return false;
  }

  public static void main(String[] s)
  {
    // System properties prior to modification.
    Properties p = (Properties)System.getProperties().clone();
    // Modification of system properties.
    System.setProperty("dummy.property", "42");
    // See if there was modification. The output is "false"
    System.out.println(isDifferent(p, System.getProperties()));
  }
}

Properties n'est pas thread-safe?

Hashtableest thread-safe, donc je m'attendais à ce que Properties le soit également, et en fait, les spécifications de l'API pour la classe Properties le confirment:

Cette classe est thread-safe: multiple les threads peuvent partager une seule Properties objet sans besoin de externe synchronisation., Formulaire sérialisé

38
coobird

Les propriétés du système sont définies par processus. Cela signifie qu'ils sont plus globaux que les champs statiques, qui sont par chargeur de classe. Ainsi, par exemple, si une seule instance de Tomcat exécute plusieurs applications Web Java, chacune ayant une classe com.example.Example avec un champ statique nommé globalField, les applications Web partageront les propriétés système, mais com.example.Example.globalField pourra être défini sur une valeur différente dans chaque cas. Webapp.

8
Max Nanasy

Il existe une copie des propriétés par machine virtuelle. Ils ont à peu près les mêmes problèmes que les autres statistiques (y compris les singletons).

En tant que piratage, je suppose que vous appelez System.setProperties à une version de Properties qui répond différemment selon le contexte (thread, pile d'appels, heure de la journée, etc.). Il pourrait également enregistrer toutes les modifications avec System.setProperty. Vous pouvez également définir une variable SecurityManager enregistre les contrôles de sécurité pour les autorisations correspondantes.

3

Leur portée est la machine virtuelle Java en cours d’exécution, mais à moins que le chargeur de classe ésotérique ne l’émette, une variable statique avec un objet de propriétés fera la même chose, et avec la possibilité de synchroniser ou de faire tout ce dont vous avez besoin.

3
Yishai

Oui, les "propriétés système" sont définies par machine virtuelle (bien qu'un certain nombre de propriétés "magiques" contiennent des informations sur le système hôte, par exemple: "os.name", "os.Arch", etc.).

En ce qui concerne votre deuxième question: je ne suis pas au courant d'un tel outil, mais si vous êtes préoccupé par la modification des propriétés système, vous pouvez utiliser un SecurityManager spécial pour empêcher (et même éventuellement suivre) les modifications des propriétés du système.

2

Lorsque vous démarrez une nouvelle machine virtuelle, elle crée une copie des variables d’environnement et les utilise tout au long de son cycle de vie. Donc, si vous apportez des modifications à cet environnement, elles resteraient confinées à cet environnement. Le comportement étrange que j'ai rencontré et sur lequel j'effectue des recherches est légèrement différent: si je lance une machine virtuelle, en déclarant certaines des variables d'environnement (argument -D sur la ligne de commande) qui affectent le comportement des bibliothèques que j'utilise dans mes applications. Mais si, à l'intérieur du code Java (où ils sont visibles), j'y apporte des modifications, il semble que ces modifications n'affectent pas le comportement des bibliothèques. Ce qui est étrange, c'est que nous sommes dans la même machine virtuelle!

0
Robin73

Vous ne dites pas quelle est votre motivation pour utiliser les propriétés du système.

Nous utilisons Spring pour notre configuration et définissons les propriétés initiales à l'aide d'un fichier de propriétés injecté dans le fichier XML. Les modifications de la configuration lorsque l'application est en cours d'exécution sont effectuées à l'aide de JMX.

Bien sûr, il existe de nombreuses autres façons de modifier la configuration en Java en utilisant un fichier de propriétés, une configuration basée sur XML, etc.

0
Fortyrunner