Domanda

Ho un oggetto statico definito nella mia classe di registrazione, sulla falsariga di:

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

Secondo il mio libro di consultazione, ciò significa che l'oggetto proprietà è condiviso da tutte le istanze della mia classe.

Trovo questa definizione insufficiente. Sto scrivendo una lezione che viene invocata più di una volta in ogni applicazione del nostro progetto.

Inoltre, il nostro progetto utilizza diversi servizi Web in esecuzione nello stesso contenitore Tomcat. Ogni servizio Web può avere più thread.

La Java Virtual Machine in esecuzione sull'host può anche eseguire una o più applicazioni client del servizio Web, che sono esterne a Tomcat.

Quindi, con questa definizione, potrei avere tomcat che esegue più servizi Web con thread, ognuno con diversi oggetti, che può contenere un'istanza della mia classe.

Potrebbero esserci anche uno o due client Web in esecuzione all'esterno di Tomcat, ma all'interno della stessa JVM. tutte di queste istanze della mia classe condividerebbe lo stesso oggetto proprietà? Ciò renderebbe JVM ampio.

Se l'oggetto statico non è non a livello di JVM, qualcuno sa a quale livello esisterebbe ciascuno? Uno per contenitore Tomcat? Uno per servizio Web e uno per applicazione client di servizio Web autonoma?

Il motivo: quando aggiorno le mie proprietà, ricevo java.lang.ConcurrentUpdateException da java.util.Properties.

Sto usando una variabile booleana statica per " bloccare " l'oggetto proprietà quando la mia classe lo aggiorna, ma ciò non impedisce al verificarsi dell'eccezione.

Questo mi porta a credere che l'oggetto statico usato nella mia classe potrebbe non essere allo stesso livello di scoping di quello usato in java.util.Properties ... Ma questa è solo un'ipotesi.

Grazie per l'aiuto.

È stato utile?

Soluzione

La probabile causa del tuo ConcurrentModificationException è che stai ripetendo i valori / le voci dell'oggetto Proprietà in un thread mentre un altro lo modifica allo stesso tempo. Non puoi farlo.

Puoi approfondire il meccanismo di blocco che menzioni qui:

  

Sto usando una variabile booleana statica per " bloccare " le proprietà oggetto quando la mia classe lo aggiorna, ma ciò non impedisce al verificarsi dell'eccezione.

Perché non sembra che si stiano utilizzando i metodi di blocco e sincronizzazione integrati in Java.

Qualcosa del genere dovrebbe impedire ai thread di leggere l'oggetto Proprietà mentre un altro thread lo aggiorna:

static Object lockObject = new Object();

...

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

Nota che dovrai farlo ogni ogni volta che accedi all'oggetto Proprietà, per leggerlo o modificarlo.

Inoltre, non consiglierei mai agli oggetti statici di condividere i dati tra tutte le istanze o i lockObjects statici - i dati globali sono malvagi - ma sembra che tu abbia bisogno di questo per qualche motivo.

Altri suggerimenti

Le statistiche non sono " condivise da tutte le istanze di una classe " - sono non correlati alle istanze; appartengono al tipo stesso . In particolare, le variabili statiche sono perfettamente utilizzabili senza nessuna istanza creata.

Questo fornisce un indizio sull'ambito della statica: sono definiti dall'oggetto Class che rappresenta la classe contenente, che è a sua volta identificata dall'oggetto ClassLoader che caricato.

A seconda di dove si trova la libreria, la variabile statica può essere JVM-wide o web-application - o forse qualcosa nel mezzo, se Tomcat supporta l'hosting multiplo (non ricordo di persona).

Guarda la documentazione Tomcat per come sono disposte le librerie e come si collegano ai caricatori di classi. Ad esempio, ecco il Tomcat 6.0 ClassLoader Guida pratica e l'equivalente per 5.5 .

Come funziona il tuo blocco booleano " " lavoro? Dovresti davvero utilizzare un blocco corretto ( sincronizzato ) per assicurarti che ogni utilizzo dell'oggetto proprietà (sia in lettura che in scrittura, incluso il blocco per l'intero periodo durante il quale si scorre attraverso di esso) sia adeguatamente bloccato.

Invece di cambiare " live " Proprietà , hai considerato di trattarlo come immutabile - quindi quando vuoi aggiornare le proprietà, ne prendi una copia, la modifichi e poi fai la copia di " live " versione? Dovresti comunque impedire a due thread diversi di apportare modifiche allo stesso tempo (o ne perderai alcuni) ma è probabile che il lato di lettura sia molto più semplice ed efficiente.

Potresti scoprire che l'ambito di tale variabile statico è limitato a uno per ClassLoader che ha caricato la tua classe. Non sono sicuro di come Tomcat disponga i suoi ClassLoaders, quindi è difficile dire quale sarà l'estensione dell'ambito in quell'ambiente.

Potrebbe essere un problema con il classloader in cui il jar che contiene la tua classe è duplicato in ogni WEB-INF / lib delle tue diverse applicazioni? In tal caso, proverei ad aggiungere questo jar alle librerie Tomcat e non all'applicazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top