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

Beispielanalyse der Intervallberechnung von MySQL-Datum und -Uhrzeit

Dieser Artikel beschreibt anhand eines Beispiels ...

So exportieren und importieren Sie SQL-Dateien unter einem Linux-Befehl

Dieser Artikel beschreibt, wie Sie SQL-Dateien mi...

Lösung für Nginx-Installationsfehler

1. Entpacken Sie nginx-1.8.1.tar.gz 2. Entpacken ...

Implementierung von proxy_pass im Nginx-Reverse-Proxy

Das Format ist einfach: Proxy_Pass-URL; Die URL u...

Eine kurze Diskussion über JavaScript-Drosselung und Anti-Shake

Inhaltsverzeichnis Drosselung und Anti-Shake Konz...

Lassen Sie uns ausführlich über Vues Mixin und Vererbung sprechen

Inhaltsverzeichnis Vorwort Mischen Mixin-Hinweis ...

Die perfekte Lösung zum Hervorheben von Schlüsselwörtern in HTML

Bei der Arbeit an einem Projekt bin ich kürzlich ...

Erkunden Sie die gängigen VMware ESXI CLI-Befehle

Inhaltsverzeichnis 【Allgemeine Befehle】 [Zusammen...

WeChat-Applet implementiert Suchfunktion und springt zur Suchergebnisseite

Suchseite: search.wxml-Seite: <view class=&quo...

Detaillierte Erklärung der Linux-Less-Befehlsbeispiele

weniger Dateiname Datei anzeigen kleiner Dateinam...