Question

J'ai un objet statique défini dans ma classe de journalisation, à l'instar de:

   class myLoggingClass {
     static java.util.Properties properties;
     ...
     ...
   }

Selon mon livre de référence, cela signifie que l'objet de propriétés est partagé par toutes les instances de ma classe.

Je trouve cette définition insuffisante. J'écris une classe qui est appelée plus d'une fois dans chaque application de notre projet.

En outre, notre projet utilise plusieurs services Web s'exécutant dans le même conteneur tomcat. Chaque service Web peut avoir plusieurs threads.

La machine virtuelle Java s'exécutant sur l'hôte peut également exécuter une ou plusieurs applications clientes de service Web, qui s'exécutent de manière externe à tomcat.

Donc, selon cette définition, tomcat peut exécuter plusieurs services Web avec des threads, chacun ayant plusieurs objets, pouvant contenir une instance de ma classe.

Il peut également y avoir un ou deux clients Web exécutés en dehors de tomcat, mais au sein de la même machine virtuelle Java. Est-ce que toutes toutes ces instances de ma classe partagent le même objet de propriétés? Cela le ferait à l’échelle de la JVM.

Si l'objet statique est pas à l'échelle de la JVM, est-ce que quelqu'un sait à quel niveau chaque objet existerait? Un conteneur par tomcat? Un par service Web et un par application client de service Web autonome?

La raison: lorsque je mets à jour mes propriétés, je reçois une exception java.lang.ConcurrentUpdateException de java.util.Properties.

J'utilise une variable booléenne statique pour " verrouiller " l'objet properties lorsque ma classe le met à jour, mais cela ne empêche pas l'exception de se produire.

Cela me porte à penser que l'objet statique utilisé dans ma classe peut ne pas être au même niveau de portée que celui utilisé dans java.util.Properties ... Mais ce n'est qu'une supposition.

Merci pour toute aide.

Était-ce utile?

La solution

La cause probable de votre ConcurrentModificationException est que vous parcourez les valeurs / entrées de l'objet Properties dans un thread alors qu'un autre le modifie simultanément. Vous ne pouvez pas faire cela.

Pouvez-vous préciser le mécanisme de verrouillage que vous mentionnez ici:

  

J'utilise une variable booléenne statique pour " verrouiller " L'objet de propriétés lorsque ma classe le met à jour, mais cela ne garde pas l'exception.

?

Parce que vous ne semblez pas utiliser les méthodes de verrouillage et de synchronisation intégrées en Java.

Quelque chose comme cela devrait empêcher les threads de lire l'objet Properties pendant qu'un autre thread le met à jour:

static Object lockObject = new Object();

...

synchronized(lockObject) {
     // access the Properties object
}

Notez que vous devrez le faire à chaque accès à l'objet Propriétés, que ce soit pour le lire ou le modifier.

En outre, je ne recommanderais jamais aux objets statiques de partager des données entre toutes les instances ou lockObjects statiques - les données globales sont néfastes - mais il semble que vous en ayez besoin pour une raison quelconque.

Autres conseils

Les statiques ne sont pas "partagées par toutes les instances d'une classe". - ils ne sont pas liés aux instances; ils appartiennent au type lui-même . En particulier, les variables statiques sont parfaitement utilisables sans aucune instance en cours de création.

Cela donne une idée de la portée de la statique: ils sont délimités par l'objet Class représentant la classe contenante, qui est à son tour délimitée par le ClassLoader qui chargé le.

En fonction de l'emplacement de la bibliothèque, la variable statique peut être étendue à l'ensemble de la JVM ou à une application Web, ou éventuellement à un élément intermédiaire, si Tomcat prend en charge l'hébergement multiple (je ne me souviens plus de façon spontanée).

Consultez la documentation de Tomcat pour connaître la structure des bibliothèques et leur relation avec les chargeurs de classes. Par exemple, voici le guide d'utilisation de Tomcat 6.0 ClassLoader et l'équivalent de la version 5.5 .

Comment votre booléen " verrouille-t-il " travail? Vous devez vraiment utiliser un verrou approprié ( synchronisé ) pour vous assurer que chaque utilisation de l'objet de propriétés (à la fois en lecture et en écriture, y compris le verrouillage pour toute la période au cours de laquelle vous le parcourez) est correctement verrouillée.

Au lieu de changer le " live " Propriétés , avez-vous envisagé de le considérer comme immuable? Ainsi, lorsque vous souhaitez mettre à jour les propriétés, vous en copiez une copie, vous la modifiez, puis vous la transmettez en "live". version? Vous auriez toujours besoin d'empêcher deux threads différents d'effectuer des modifications en même temps (sinon vous en perdriez certaines), mais cela rendra probablement la lecture beaucoup plus facile et plus efficace.

Vous constaterez peut-être que la portée d'une telle variable statique est limitée à une par chargeur de classe ayant chargé votre classe. Je ne sais pas comment Tomcat organise ses ClassLoaders. Il est donc difficile de dire quelle sera l'étendue de la portée de cet environnement.

Serait-ce un problème de chargeur de classe où le jar contenant votre classe est dupliqué dans chaque WEB-INF / lib de vos différentes applications? Si tel est le cas, j’essaierai d’ajouter ce fichier jar aux bibliothèques Tomcat et non à l’application.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top