2009-12-29 13 views
13

Jestem początkującym użytkownikiem języka Java i dopiero zaczynam poznawać koncepcję programów ładujących klasy. W tej chwili mam pewne problemy z log4j dotyczące używania klasowego modułu ładowania wątków.log4j i obiekt ładujący klasy kontekstu wątku

Dostaję następujące błędy: 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".

Moja aplikacja działa mniej więcej w ten sposób: Na startowych URLClassLoader # 1 jest skonstruowany i wczytuje niektóre klasy, klasy te użyciu log4j. Później konstruuje się URLClassLoader # 2 (który ma URLClassLoader # 1 jako swój rodzic) i ładuje więcej klas, te klasy również używają log4j. Gdy do załadowania tych klas zostanie użyty parametr URLClassLoader # 2, pojawi się powyższy komunikat o błędzie (jest jeszcze kilka z tym samym problemem).

Obecny obejście zrobiłem było ustawić kontekst aktualnego wątku classloader do URLClassLoader # 2 przed włożeniem problematycznych klas i resetowanie go do starego później:

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

Chociaż to działa, nie jestem pewnie, czy to właściwe podejście.

Każdy wgląd w tej sprawie zostanie doceniony. Dlaczego log4j zmusza mnie do bałaganu z modułem kontekstowym wątków? Dlaczego nie pozwolić mi przejść do programu ładującego klasy (i użyć domyślnego programu ładującego, gdy tego nie zrobię) zamiast używać tego wątku?

+0

Uratowałeś mi życie zadając pytanie, że utknąłem na 3 dni z podobnym problemem! Nie ustawiłem "thread.setContextClassLoader", i to jest w porządku! To naprawdę miłe, mimo że jesteś początkującym użytkownikiem w Javie! –

Odpowiedz

15

Wygląda na to, że natknąłeś się na poważny problem z log4j (i biblioteką Apache Commons Logging), a mianowicie, że mają oni absurdalnie trudny czas odkrywania i interakcji z odpowiednimi modułami ładującymi klasy, gdy są używane. Jest bardzo gęste wyjaśnienie, wraz z przykładami, here; komunikat "zabierz z domu" jest taki, że jedną z głównych sił napędowych nowego szkieletu logowania SLF4J było całkowite wyeliminowanie tych problemów. Możesz zamienić go i sprawdzić, czy twoje życie jest łatwiejsze.

+0

Nie jestem pewien, czy jest możliwe, abyśmy zaczęli używać czegoś innego w tym momencie. Jaki jest sugerowany sposób radzenia sobie z tym problemem log4j? –

+1

Szczerze mówiąc, nie mogę powiedzieć, ponieważ jest to problem wystarczająco zły, że teraz wytrwale unikam logowania log4j i Apache Commons. Realistycznie rzecz biorąc, powinieneś być w stanie przeprowadzić migrację do SLF4J w sposób trywialny - zobacz http://www.slf4j.org/legacy.html, aby dowiedzieć się, w jaki sposób SLF4J zawiera "przejściówki przejściowe", które pozwalają twojemu kodowi nadal wykonywać połączenia z log4j i mieć te połączenia przechwycone przez SLF4J. W ten sposób możesz użyć SLF4J natywnie w dowolnym nowym kodzie i przenieść swój stary, wykorzystujący log4j kod do SLF4J w czasie wolnym. – delfuego

+0

+1 dla podpowiedzi, aby uniknąć Log4j i JCL. Zostały one zastąpione przez SLF4j, który ma również warstwy kompatybilności dla log4j i jcl. Zrobiliśmy to w WSZYSTKICH naszych projektach z dokładnie tych powodów. – mhaller

Powiązane problemy