web-dev-qa-db-fra.com

Ordre de chargement des fichiers jar à partir du répertoire lib

Quelqu'un pourrait-il expliquer l'ordre dans lequel les fichiers jar sont chargés à partir du répertoire lib dans Tomcat? Est-ce par ordre alphabétique? Au hasard? Ou une autre commande?

36
Damien

Tout est décrit dans HOWTO ClassLoading de Tomcat . Ce n'est pas nécessairement par ordre alphabétique. Si vous avez observé ce comportement, il ne devrait absolument pas être utilisé si vous avez l'intention de garder votre application Web portable sur tous les serveurs. Par exemple, Tomcat 6 le commande "par coïncidence", mais pas Tomcat 8.

En résumé, l'ordre de chargement est le suivant:

  1. bootstrap/system (JRE/lib, puis server.loader)
  2. bibliothèques Webapp (WEB-INF/classes, puis WEB-INF/lib)
  3. bibliothèques communes (common.loader, puis Tomcat/lib)
  4. bibliothèques partagées par webapp (shared.loader)

Si vous souhaitez garantir que JAR X est chargé - après JAR Y, vous devez alors placer JAR X à l'un des emplacements qui apparaissent plus tard dans la liste ci-dessus.

Il existe cependant des exceptions, qui sont mentionnées dans les Documents Tomcat

Enfin, le chargeur de classe d'application Web délègue toujours en premier les classes API JavaEE pour les spécifications implémentées par Tomcat (Servlet, JSP, EL, WebSocket). Tous les autres chargeurs de classe dans Tomcat suivent le modèle de délégation habituel.

Cela signifie que si une webapp contient des classes JavaEE (javax.*), alors il sera ignoré par Tomcat.

Pour chaque chargeur, les classes sont simplement chargées par la JVM dans l'ordre chaque fois qu'elles doivent être importées/exécutées et ne sont pas encore chargées.

36
BalusC

En fait, c'est est ordre alphabétique! (Dans un répertoire spécifique, par exemple le répertoire 'lib' mentionné par l'affiche originale.)

Plus précisément, si vous regardez la source de Tomcat 6, dans la classe FileDirContext, la méthode list() appelle Arrays.sort() sur le tableau des noms de fichiers des pots trouvés .

J'ai également testé cela manuellement. Je crée une guerre avec un JSP qui appelle HelloWorld.getGreeting(), et place deux jars presque identiques contenant des versions légèrement différentes de HelloWorld dans le répertoire WEB-INF/lib. L'un dit "Bonjour, monde", l'autre "Au revoir, monde cruel".

Si je nomme la version "Hello, world" a.jar et la version "goodbye" b.jar, et que je redémarre Tomcat, j'obtiens le texte "Hello". Si je nomme les pots dans l'autre sens et redémarre Tomcat, j'obtiens le texte "Au revoir".

Pour autant que j'ai pu le déterminer, ce comportement n'est PAS documenté, NON spécifié et ne doit PAS être utilisé. Mais c'est alphabétique - pour l'instant.

32
Charles Roth

Commande des fichiers jar chargés dans le dossier WEb-INF/lib.

Pour Tomcat 5-7, l'ordre est alphabétique. Il utilise le tri.

Pour Tomcat 8, le système de fichiers sous-jacent décide au hasard.

https://issues.Apache.org/bugzilla/show_bug.cgi?id=57129

23
user2193008

J'accepte totalement la réponse fournie par BalusC. Le seul point à ajouter est quand il s'agit de charger un JAR à partir du chargeur de classe respectif, il vérifie l'ordre alphabétique.

J'ai eu une situation pour charger "XSSFWorkbook" dans mon application Web pour lire les données de la feuille Excel et j'avais deux JARS "poi-ooxml-3.9.jar" et "org.Eclipse.birt.runtime_4.3.1.v20130918-1142.jar" avec le même nom de classe et la même structure de package. J'ai simplement remanié le dernier donc dans son ordre alphabétique vient à côté du précédent et ça m'a fait un truc. Je voulais juste partager la même chose.

Bonne chance

1

Dans notre environnement WebSphere, différentes machines chargent le bocal dans un ordre différent. Je suis donc d'accord avec user2193008. Nous rencontrons un problème de chargeur de classe dans Production env où le même code fonctionne bien dans un environnement inférieur. Nous avons résolu le problème en supprimant le bocal en double dans la bibliothèque, par exemple, il existe deux versions des jarres à ressort, spring_v1.jar et spring_v2.jar, si le chargeur de classe charge d'abord la v1, le code fonctionne correctement, mais si le chargeur de classe charge la première v2, des problèmes.

0
Feng Zhang