2009-12-29 12 views
13

Sono un principiante di Java e sto iniziando a capire il concetto di programma di caricamento classi. In questo momento sto riscontrando alcuni problemi con log4j riguardo all'uso del classloader del contesto dei thread.log4j e il contestloader del contesto thread

sto ottenendo i seguenti errori: A "org.apache.log4j.ConsoleAppender" object is not assignable to a "org.apache.log4j.Appender" variable. The class "org.apache.log4j.Appender" was loaded by [[email protected]] whereas object of type "org.apache.log4j.ConsoleAppender" was loaded by [[email protected]]. Could not instantiate appender named "CONSOLE".

La mia applicazione funziona più o meno in questo modo: Su init URLClassLoader # 1 è costruito e carica alcune classi, queste classi utilizzano log4j. Successivamente viene costruito URLClassLoader # 2 (che ha URLClassLoader # 1 come genitore) e carica qualche altra classe, queste classi usano anche log4j. Quando URLClassLoader # 2 viene utilizzato per caricare queste classi, viene visualizzato il messaggio di errore sopra riportato (ce ne sono ancora un paio con lo stesso problema).

La soluzione attuale che ho fatto è stato quello di impostare la corrente di caricamento classe contesto thread per URLClassLoader # 2 prima di caricare le classi problematici, e resettarlo a quello vecchio in seguito:

ClassLoader urlClassLoader; // this is URLClassLoader #2 
Thread thread = Thread.currentThread(); 
ClassLoader loader = thread.getContextClassLoader(); 
thread.setContextClassLoader(urlClassLoader); 
try { 
    urlClassLoader.loadClass(...) 
} finally { 
    thread.setContextClassLoader(loader); 
} 

Anche se questo funziona, io non sono certo se è l'approccio giusto

Qualsiasi commento su questo argomento sarà apprezzato. Inoltre, perché log4j mi costringe a fare casino con il classloader del contesto dei thread? Perché non lasciarmi passare in un caricatore di classe (e usarne uno predefinito quando non lo faccio) invece di usare quello del thread?

+0

Mi hai salvato la vita con la tua domanda, sono stato bloccato per 3 giorni con un problema simile! Non ho impostato "thread.setContextClassLoader", e con quello va bene! E 'davvero bello nonostante tu fossi un novizio in java! –

risposta

15

È sembrano aver inciampato sul principale problema con log4j (e la biblioteca Logging Apache Commons), vale a dire che essi hanno un tempo ridicolmente difficile scoprire e interagire con i classloader giuste sono in uso. C'è una spiegazione molto densa, completa di esempi, here; il messaggio da portare a casa è che una delle principali forze trainanti per il nuovo framework di registrazione SLF4J era eliminare completamente questi problemi. Potresti volerlo scambiare e vedere se la tua vita è resa più facile.

+0

Non sono sicuro che sia possibile per noi iniziare a utilizzare qualcos'altro a questo punto. Qual è il modo suggerito per affrontare questo problema di log4j? –

+1

Onestamente, non posso dire, perché è un problema abbastanza grave che ora evito assiduamente log4j e Apache Commons Logging. Realisticamente, però, dovresti essere in grado di migrare banalmente a SLF4J - vedi http://www.slf4j.org/legacy.html per informazioni su come SLF4J viene fornito con "bridge adapter" che consentono al tuo codice di effettuare ancora chiamate a log4j e avere quelle chiamate intercettate da SLF4J. In questo modo, è possibile utilizzare SLF4J in modo nativo in qualsiasi nuovo codice e migrare il vecchio codice log4j-using a SLF4J a proprio piacimento. – delfuego

+0

+1 per il suggerimento per evitare Log4j e JCL. Vengono sostituiti da SLF4j, che ha anche livelli di compatibilità per log4j e jcl. Lo abbiamo fatto in TUTTI i nostri progetti proprio per queste ragioni. – mhaller

Problemi correlati