2009-12-29 13 views
13

Soy un novato en Java y estoy empezando a descubrir el concepto de cargadores de clases. En este momento estoy teniendo algunos problemas con log4j con respecto al uso del gestor de clases de contexto del hilo.log4j y el gestor de clase de contexto de hilos

Me estoy poniendo los siguientes errores: 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".

Mi aplicación funciona más o menos de esta manera: En init URLClassLoader # 1 se construye y se carga algunas clases, estas clases utilizan log4j. Más tarde se construye URLClassLoader # 2 (que tiene URLClassLoader # 1 como su principal) y carga algunas clases más, estas clases también usan log4j. Cuando URLClassLoader # 2 se utiliza para cargar estas clases, aparece el mensaje de error anterior (hay un par más con el mismo problema).

La solución actual que hice fue para establecer la corriente del cargador de clases de contexto de subproceso a URLClassLoader # 2 antes de cargar las clases problemáticas, y que se quede en el viejo después:

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

Aunque esto funciona, no estoy seguro si es el enfoque correcto.

Cualquier apreciación sobre este asunto será apreciada. Además, ¿por qué log4j me obliga a meterme con el cargador de clases de contexto del hilo? ¿Por qué no me deja pasar un cargador de clases (y usar uno predeterminado cuando no lo hago) en lugar de usar el del hilo?

+0

¡Salvaste mi vida con tu pregunta, estuve trabada durante 3 días con un problema similar! No he configurado "thread.setContextClassLoader", ¡y con eso está bien! ¡Es realmente agradable a pesar de que eras un novato en Java! –

Respuesta

15

Pareces haber tropezado con el principal problema con log4j (y la biblioteca de registro de Apache Commons), es decir, que tienen un tiempo ridículamente difícil para descubrir e interactuar con los cargadores de clases correctos a medida que se utilizan. Hay una explicación muy densa, completa con ejemplos, here; El mensaje principal es que una de las principales fuerzas impulsoras para el nuevo marco de registro SLF4J fue eliminar estos problemas por completo. Es posible que desee cambiarlo y ver si su vida se hace más fácil.

+0

No estoy seguro de si es factible para nosotros comenzar a usar otra cosa en este momento. ¿Cuál es la forma sugerida de lidiar con este problema de log4j? –

+1

Honestamente, no puedo decirlo, porque es un problema bastante grave que ahora evito asiduamente log4j y Apache Commons Logging. De forma realista, sin embargo, debería poder migrar a SLF4J trivialmente; consulte http://www.slf4j.org/legacy.html para obtener información sobre cómo SLF4J viene con "adaptadores de puente" que permiten que su código realice llamadas a log4j y hacer que esas llamadas sean interceptadas por SLF4J. De esta forma, puede usar SLF4J de forma nativa en cualquier código nuevo y migrar el antiguo código que utiliza log4j a SLF4J cuando lo desee. – delfuego

+0

+1 para la sugerencia de evitar Log4j y JCL. Son reemplazados por SLF4j, que también tiene capas de compatibilidad para log4j y jcl. Hemos hecho eso en TODOS nuestros proyectos por exactamente esas razones. – mhaller

Cuestiones relacionadas