Kann mir jemand die Reihenfolge erklären, in der die jar-Dateien aus dem lib-Verzeichnis in Tomcat geladen werden? Ist es alphabetisch? Nach dem Zufallsprinzip? Oder eine andere Reihenfolge?
Antworten
Zu viele Anzeigen?Das alles ist beschrieben in Tomcats ClassLoading HOW-TO . Es ist nicht unbedingt in alphabetischer Reihenfolge. Wenn Sie dieses Verhalten beobachtet haben, sollte es auf keinen Fall verlassen, wenn Sie beabsichtigen, Ihre Webanwendung über mehrere Server hinweg portabel zu halten. Tomcat 6 beispielsweise bestellt es "zufällig", Tomcat 8 jedoch nicht.
Zusammengefasst lautet die Reihenfolge der Beladung wie folgt:
- bootstrap/system (
JRE/lib
entoncesserver.loader
) - Webapp-Bibliotheken (
WEB-INF/classes
entoncesWEB-INF/lib
) - gemeinsame Bibliotheken (
common.loader
entoncesTomcat/lib
) - gemeinsam genutzte Webapp-Bibliotheken (
shared.loader
)
Wenn Sie sicherstellen möchten, dass JAR X geladen ist nach JAR Y, dann müssen Sie JAR X an einer der Stellen einfügen, an denen später in der obigen Auflistung.
Es gibt jedoch Ausnahmen, die in den folgenden Abschnitten erwähnt werden Tomcat-Dokumente
Schließlich delegiert der Klassenlader für Webanwendungen immer zuerst die JavaEE-API-Klassen für die von Tomcat implementierten Spezifikationen (Servlet, JSP, EL, WebSocket). Alle anderen Klassenlader in Tomcat folgen dem üblichen Delegationsmuster.
Das heißt, wenn eine Webanwendung JavaEE-Klassen enthält ( javax.*
), dann wird er vom Tomcat ignoriert.
Für jeden Lader werden die Klassen von der JVM nur in der Reihenfolge geladen, in der sie importiert/ausgeführt werden müssen und noch nicht geladen sind.
Eigentlich ist es es in alphabetischer Reihenfolge! (Innerhalb eines bestimmten Verzeichnisses, z. B. des Verzeichnisses "lib", das der ursprüngliche Poster erwähnt hat).
Genauer gesagt, wenn Sie sich den Quelltext von Tomcat 6 ansehen, finden Sie in der Klasse FileDirContext
die Methode list()
ruft auf. Arrays.sort()
auf das Array der Dateinamen der gefundenen Jars.
Ich habe dies auch manuell getestet. Ich erstelle ein War mit einem JSP, das Folgendes aufruft HelloWorld.getGreeting()
und stellen zwei fast identische Gläser mit leicht unterschiedlichen Versionen von HelloWorld
in das Verzeichnis WEB-INF/lib. Auf dem einen steht "Hallo, Welt", auf dem anderen "Auf Wiedersehen, grausame Welt".
Wenn ich die "Hello, world"-Version a.jar und die "goodbye"-Version b.jar benenne und Tomcat neu starte, erhalte ich den "Hello"-Text. Wenn ich die Jars andersherum benenne und Tomcat neu starte, erhalte ich den Text "Goodbye".
Soweit ich feststellen konnte, ist dieses Verhalten NICHT dokumentiert, NICHT spezifiziert und man sollte sich NICHT darauf verlassen. Aber es ist alphabetisch - im Moment.
Ich stimme der Antwort von BalusC vollkommen zu. Der einzige Punkt, den ich hinzufügen möchte, ist, dass beim Laden eines JARs aus dem jeweiligen Classloader die alphabetische Reihenfolge überprüft wird.
Ich hatte eine Situation zu laden "XSSFWorkbook" in meiner Web-Anwendung zum Lesen von Daten aus Excel-Blatt und hatte zwei JARS "poi-ooxml-3.9.jar" und "org.eclipse.birt.runtime_4.3.1.v20130918-1142.jar" mit gleichen Klassennamen und Paketstruktur. Ich habe einfach die letztere in der alphabetischen Reihenfolge neben die frühere gestellt und das hat bei mir geklappt. Wollte nur das gleiche zu teilen.
Viel Glück
In unserer WebSphere-Umgebung laden verschiedene Rechner die Jar-Dateien in unterschiedlicher Reihenfolge. Ich stimme also mit user2193008 überein. Wir haben ein Problem mit dem Klassenlader in der Produktionsumgebung, wo derselbe Code in einer niedrigeren Umgebung gut funktioniert. Wir haben das Problem behoben, indem wir ein doppeltes Jar in der Bibliothek entfernt haben. Zum Beispiel gibt es zwei Versionen von Spring-Jars, spring_v1.jar und spring_v2.jar, wenn Classloader zuerst v1 lädt, funktioniert der Code gut, aber wenn Classloader zuerst v2 lädt, gibt es Probleme.