Analyse und Lösung des abnormalen Problems beim Laden von JAR in Tomcat

Analyse und Lösung des abnormalen Problems beim Laden von JAR in Tomcat

Beschreibung des Phänomens:

Das Projekt verwendet Springboot, um ein Webprojekt zu starten. Während der Startphase wird in der Konsole eine Ausnahme angezeigt: „1.10.3-1.4.3\hdf5.jar Das System kann die angegebene Datei nicht finden.“ Obwohl diese Ausnahmen den normalen Betrieb des Projekts nicht beeinträchtigen, ist das Sehen dieser Ausnahmen für einen strengen Techniker wie das Sehen eines Feindes und muss so schnell wie möglich beseitigt werden.

java.io.FileNotFoundException: D:\.m2\repository\org\bytedeco\javacpp-presets\hdf5-platform\1.10.3-1.4.3\hdf5.jar (Das System kann die angegebene Datei nicht finden.)
 bei java.util.zip.ZipFile.open (native Methode)
 bei java.util.zip.ZipFile.<init>(ZipFile.java:225)
 bei java.util.zip.ZipFile.<init>(ZipFile.java:155)
 bei java.util.jar.JarFile.<init>(JarFile.java:166)
 bei java.util.jar.JarFile.<init>(JarFile.java:130)
 bei org.apache.tomcat.util.compat.JreCompat.jarFileNewInstance(JreCompat.java:188)
 bei org.apache.tomcat.util.scan.JarFileUrlJar.<init>(JarFileUrlJar.java:65)
 bei org.apache.tomcat.util.scan.JarFactory.newInstance(JarFactory.java:49)
 bei org.apache.tomcat.util.scan.StandardJarScanner.process(StandardJarScanner.java:374)
 bei org.apache.tomcat.util.scan.StandardJarScanner.processURLs(StandardJarScanner.java:309)
 bei org.apache.tomcat.util.scan.StandardJarScanner.doScanClassPath(StandardJarScanner.java:266)
 bei org.apache.tomcat.util.scan.StandardJarScanner.scan(StandardJarScanner.java:229)
 bei org.apache.jasper.servlet.TldScanner.scanJars(TldScanner.java:262)
 bei org.apache.jasper.servlet.TldScanner.scan(TldScanner.java:104)
 bei org.apache.jasper.servlet.JasperInitializer.onStartup(JasperInitializer.java:101)
 bei org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5204)
 bei org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
 bei org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1421)
 bei org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1411)
 bei java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
 bei java.util.concurrent.FutureTask.run(FutureTask.java)
 bei java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 bei java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 bei java.lang.Thread.run(Thread.java:748)

2019-03-29 18:09:08.303 WARNUNG 16940 --- [ost-startStop-1] oatomcat.util.scan.StandardJarScanner: Fehler beim Scannen von [file:/D:/.m2/repository/org/bytedeco/javacpp-presets/hdf5-platform/1.10.3-1.4.3/hdf5-linux-x86.jar] aus der Klassenladerhierarchie.

java.io.FileNotFoundException: D:\.m2\repository\org\bytedeco\javacpp-presets\hdf5-platform\1.10.3-1.4.3\hdf5-linux-x86.jar (Das System kann die angegebene Datei nicht finden.)
......
2019-03-29 18:09:08.578 WARNUNG 16940 --- [ost-startStop-1] oatomcat.util.scan.StandardJarScanner: Fehler beim Scannen von [file:/D:/.m2/repository/org/bytedeco/javacpp-presets/hdf5-platform/1.10.3-1.4.3/hdf5-linux-x86_64.jar] aus der Klassenladerhierarchie.

java.io.FileNotFoundException: D:\.m2\repository\org\bytedeco\javacpp-presets\hdf5-platform\1.10.3-1.4.3\hdf5-linux-x86_64.jar (Das System kann die angegebene Datei nicht finden.)

Beschreibung der Projektumgebung

  • tomcat: Verwenden Sie die integrierte Springboot-Version 8.5.29
  • Abhängigkeitsverwaltung mit Maven
  • Die Spring Boot-Version ist 2.0.1
  • Die Spring-Framework-Version ist 5.0.5
  • Das Projekt verweist auf Deep Learn 4 Java (eine großartige Java-Bibliothek für maschinelles Lernen).
 <Abhängigkeit>
 <groupId>org.deeplearning4j</groupId>
 <artifactId>deeplearning4j-core</artifactId>
 <version>1.0.0-beta3</version>
 </Abhängigkeit>

Problematische Jar-Abhängigkeiten

Tracking-Analyse

Da der Fehler während der Startphase gemeldet wird, suchen Sie die Startklasse und fügen Sie einen Haltepunkt hinzu, verfolgen Sie Schritt für Schritt, in welcher Phase der Fehler gemeldet wird, und analysieren Sie dann die Fehlerursache. Ich habe den Springboot-Code verfolgt und debuggt und den Ladeort des Jars gefunden. Die wichtigsten Klassen und Methoden sind wie folgt:

Tracking-Klasse org.apache.tomcat.util.scan.StandardJarScanner

Methode doScanClassPath(...)

Diese Methode durchläuft alle Klassenlader und lädt das JAR-Paket in jeden Klassenlader.

Der rote Teil des obigen Symbols ist der Schlüsselcode, in dem die Variable classPathUrlsToProcess alle zu ladenden JAR-Informationen speichert, hauptsächlich die JAR-Paketpfadinformationen. Wir können sehen, dass es dasselbe ist wie das JAR-Paket, das wir in Maven gesehen haben.

  • Methode processURLs(...)

Diese Methode führt einen Stapelvorgang für alle JARs des aktuellen Klassenladers aus, d. h. classPathUrlsToProcess, und verarbeitet dann jedes JAR-Paket. Die Schlüsselcodes lauten wie folgt.

  • Methode process()

Mit dieser Methode werden alle Jars geladen und analysiert. Der Schwerpunkt liegt dabei auf

Prozessmanifest (JAR, istWebanwendung, KlassenpfadURLszuProzess) 

  • Methode processManifest

Diese Methode verarbeitet die Manifestdatei im JAR, trennt den Klassenpfad in der Manifestdatei und fügt den Inhalt als neues abhängiges JAR in classPathUrlsToProcess ein (die Methode processURLs lädt das JAR im Stapelergebnis).

Ursachenanalyse

Tatsächlich liegt das Problem im Klassenpfad in der Manifestdatei. Durch die Analyse des Codes wissen wir, dass Tomcat nicht nur das von unserem Maven verwaltete JAR-Paket lädt, sondern auch die Manifestdatei im JAR analysiert. Wenn darin ein Klassenpfad vorhanden ist, fügt es den Inhalt auch der JAR-Paketabhängigkeit hinzu und lädt diese JAR-Pakete.

Wir öffnen als Beispiel die Manifestdatei von hdf5-1.10.3-1.4.3.jar, um zu sehen, wo der Fehler auftritt.

Haben Sie bemerkt, dass das JAR-Paket hier weder Pfad noch Versionsnummer hat, was dazu führt, dass Tomcat es entsprechend dem Pfad von hdf5-1.10.3-1.4.3.jar lädt?

Allerdings sind diese Jars an den entsprechenden Stellen in unserem Projekt nicht vorhanden, was zu der Ausnahme führt, dass die Jars nicht gefunden werden können. Wir haben diese Jars tatsächlich in unserem Projekt, aber die Pfade und Namen sind unterschiedlich. Auf der linken Seite des Bildes oben können Sie sehen, dass diese Jars bereits in Maven verfügbar sind, aber die Versionsnummern werden nach den Namen hinzugefügt und die Pfade befinden sich in ihren jeweiligen Maven-Repositorys.

An diesem Punkt haben wir die Ursache des Problems herausgefunden und überlegen nun, wie es sich lösen lässt.

Lösung

Option 1:

Löschen Sie den Klassenpfad im Manifest oder löschen Sie die Manifestdatei, um das Laden nicht vorhandener JAR-Pakete zu vermeiden. Allerdings können Ihre Änderungen bei jeder Aktualisierung von Maven überschrieben werden, wodurch die Ausnahme erneut auftritt.

Option 2:

Kopieren Sie das entsprechende JAR-Paket gemäß dem beim Laden angegebenen Pfad und benennen Sie es um, um die Versionsnummer zu entfernen. Dadurch entsteht jedoch eine JAR-Redundanz, und dasselbe JAR wird zweimal geladen.

Option 3:

Führen Sie ein Downgrade der Tomcat-Version auf 8.5.0 oder früher durch. In Version 8.5.0 wird das Manifest nicht analysiert und geladen, daher tritt unsere Ausnahme nicht auf.

Option 4

Fügen Sie Codeeinstellungen hinzu, um Manifestdateien nicht zu scannen.

 @Bohne
 öffentliche TomcatServletWebServerFactory tomcatFactory() {
  returniere neue TomcatServletWebServerFactory() {
   @Überschreiben
   geschützt void postProcessContext(Kontext Kontext) {
    ((StandardJarScanner) Kontext.getJarScanner()).setScanManifest(false);
   }
  };
 } 

Zusammenfassen:

Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Lernwert für Ihr Studium oder Ihre Arbeit hat. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM.

Das könnte Sie auch interessieren:
  • Implementierungsmethode und Beispielcode des Tomcat-Klassenladers
  • Lösen Sie das Problem, dass Eclipse beim Starten von Tomcat keine Webprojekte laden kann
  • Detaillierte Erläuterung der Hot-Deployment- und Hot-Loading-Methoden von Tomcat
  • Lösung für Tomcats Fehler beim Laden statischer Ressourcendateien wie CSS und JS
  • Kennen Sie den Klassenlader und Sicherheitsmechanismus in Java Tomcat?

<<:  MySQL 5.7.20 Win64 Installations- und Konfigurationsmethode

>>:  Sprechen Sie über nextTick in Vue

Artikel empfehlen

JavaScript imitiert den Taobao-Lupeneffekt

In diesem Artikel wird der spezifische Code für J...

So gehen Sie mit Zeitzonenproblemen in Docker um

Hintergrund Als ich in diesen beiden Tagen Docker...

Installation und Verwendung der MySQL MyCat-Middleware

1. Was ist mycat Ein vollständig Open Source-Groß...

Einführung in die wichtigsten Browser und ihre Kernel

Trident-Kern: IE, MaxThon, TT, The World, 360, So...

Vue.js verarbeitet Icon-Symbole über Komponenten

Icon-Icon-Verarbeitungslösung Das Ziel dieses Dat...

WebWorker kapselt JavaScript-Sandbox-Details

Inhaltsverzeichnis 1. Szenario 2. Implementieren ...

So kapseln Sie die Rich-Text-Komponente von WangEditor in Angular

Die Rich-Text-Komponente ist eine sehr häufig ver...