Tomcat unterbricht den übergeordneten Delegierungsmechanismus, um eine Isolierung von Webanwendungen zu erreichen

Tomcat unterbricht den übergeordneten Delegierungsmechanismus, um eine Isolierung von Webanwendungen zu erreichen

Tomcat unterbricht die übergeordnete Delegierung durch den benutzerdefinierten Klassenlader WebAppClassLoader, d. h., es schreibt die Methoden findClass und loadClass des JVM-Klassenladers ClassLoader neu, um dem Laden von Klassen im Web-Anwendungsverzeichnis Priorität einzuräumen.

Tomcat ist für das Laden unserer Servlet-Klasse und des JAR-Pakets verantwortlich, von dem das Servlet abhängt. Tomcat selbst ist auch ein Java-Programm und muss daher seine eigenen Klassen und abhängigen JAR-Pakete laden.

Wenn Sie zwei Webanwendungen auf Tomcat ausführen und diese über Servlets mit demselben Namen, aber unterschiedlichen Funktionen verfügen, muss Tomcat diese beiden Servlet-Klassen mit demselben Namen gleichzeitig laden und verwalten, um sicherzustellen, dass es nicht zu Konflikten kommt. Daher müssen Klassen zwischen Webanwendungen isoliert werden

Wenn zwei Webanwendungen beide von derselben JAR-Datei eines Drittanbieters wie Spring abhängen, muss Tomcat nach dem Laden der Spring-JAR-Datei in den Speicher sicherstellen, dass die beiden Webanwendungen sie gemeinsam nutzen können, d. h. die Spring-JAR-Datei wird nur einmal geladen. Andernfalls wird der Speicher der JVM zu groß, wenn die Anzahl der JAR-Dateien von Drittanbietern zunimmt.
Daher ist es wie bei der JVM notwendig, die Klassen von Tomcat selbst und die Klassen der Webanwendung zu isolieren.

Hierarchie des Tomcat-Klassenladers

Tomcats Klassenladerhierarchie

Die ersten drei sind Loader-Instanznamen, keine Klassennamen.

WebAppClassLoader

Wenn Sie den standardmäßigen AppClassLoader der JVM zum Laden einer Webanwendung verwenden, kann AppClassLoader nur eine Servlet-Klasse laden. Beim Laden einer zweiten Servlet-Klasse mit demselben Namen gibt AppClassLoader die Class-Instanz der ersten Servlet-Klasse zurück.
Denn aus Sicht von AppClassLoader kann eine Servlet-Klasse mit gleichem Namen nur einmal geladen werden.

Daher passt Tomcat einen Klassenlader (WebAppClassLoader) an und erstellt für jede Webanwendung eine WebAppClassLoader- Instanz.

Die eigenen Java-Klassen und abhängigen JAR-Pakete jeder Web-Anwendung werden in WEB-INF/classes und WEB-INF/lib abgelegt und alle vom WebAppClassLoader geladen.

Die Context-Container-Komponente entspricht einer Web-Anwendung. Daher erstellt und verwaltet jeder Context-Container eine WebAppClassLoader-Loader-Instanz.
Von verschiedenen Loader-Instanzen geladene Klassen werden als unterschiedliche Klassen betrachtet, auch wenn sie denselben Klassennamen haben. Dies entspricht der Erstellung gegenseitig isolierter Java-Klassenräume innerhalb der JVM. Jede Webanwendung hat ihren eigenen Klassenraum und Webanwendungen sind durch ihre eigenen Klassenlader voneinander isoliert.

SharedClassLoader

Wie können zwei Webanwendungen Bibliotheksklassen gemeinsam nutzen, ohne dass dieselbe Klasse wiederholt geladen wird?

Jeder untergeordnete Loader des übergeordneten Delegierungsmechanismus kann Klassen über den übergeordneten Loader laden. Erwägen Sie daher, die gemeinsam zu nutzenden Klassen in den Ladepfad des übergeordneten Loaders einzufügen.

Auf diese Weise teilen Anwendungen JRE-Kernklassen.
Tomcat hat einen Klassenlader SharedClassLoader als übergeordneten Lader von WebAppClassLoader erstellt, um zwischen Web-Anwendungen gemeinsam genutzte Klassen zu laden.

Wenn WebAppClassLoader eine Klasse nicht lädt, beauftragt es den übergeordneten Loader SharedClassLoader mit dem Laden der Klasse. SharedClassLoader lädt die gemeinsam genutzte Klasse in das angegebene Verzeichnis und gibt sie dann an WebAppClassLoader zurück, um das Problem der gemeinsamen Nutzung zu lösen.

CatalinaClassLoader

Wie isoliert man Tomcats eigene Klassen von den Klassen der Webanwendung?

Geschwisterbeziehung: Zwei Klassenlader sind parallel. Sie können denselben übergeordneten Loader haben, aber die von den beiden Geschwisterklassenladern geladenen Klassen sind isoliert.

Daher hat Tomcat CatalinaClassLoader erstellt, um Tomcats eigene Klassen zu laden.

Die Frage ist: Was sollen wir tun, wenn einige Klassen zwischen Tomcat und verschiedenen Webanwendungen geteilt werden müssen?

Allgemeiner ClassLoader

Das Teilen beruht noch immer auf der Vater-Sohn-Beziehung.
Fügen Sie einen weiteren CommonClassLoader als übergeordneten Loader von CatalinaClassLoader und SharedClassLoader hinzu.

Die Klassen, die CommonClassLoader laden kann, können von CatalinaClassLoader und SharedClassLoader verwendet werden, während die Klassen, die CatalinaClassLoader und SharedClassLoader laden können, voneinander isoliert sind. WebAppClassLoader kann von SharedClassLoader geladene Klassen verwenden, aber jede WebAppClassLoader-Instanz ist voneinander isoliert.

Problem mit der Federbelastung

Wenn eine Klasse vom Klassenlader A geladen wird, werden standardmäßig auch die abhängigen Klassen der Klasse vom gleichen Klassenlader geladen.
Beispielsweise muss Spring als Bean-Factory Instanzen von Business-Klassen erstellen und diese Klassen laden, bevor Instanzen von Business-Klassen erstellt werden. Spring lädt Business-Klassen durch den Aufruf von Class.forName. Werfen wir einen Blick auf den Quellcode von forName:

öffentliche statische Klasse<?> fürName(String className) {
    Klasse<?> Anrufer = Reflection.getCallerClass();
    returniere forName0(Klassenname, true, ClassLoader.getClassLoader(Anrufer), Anrufer);
}

Der Anrufer, der Loader von Spring, wird zum Laden der Business-Klasse verwendet.

Zwischen Webanwendungen gemeinsam genutzte JAR-Dateien können von SharedClassLoader geladen werden, um wiederholtes Laden zu vermeiden. Als gemeinsam genutzte JAR-Datei eines Drittanbieters wird Spring von SharedClassLoader geladen. Spring muss auch Geschäftsklassen laden. Gemäß der vorherigen Regel wird der Klassenlader, der Spring lädt, auch zum Laden von Geschäftsklassen verwendet. Die Geschäftsklassen befinden sich jedoch im Webanwendungsverzeichnis und nicht im Ladepfad von SharedClassLoader. Was soll ich tun?

Thread-Kontextlader

Es gibt also einen Thread-Kontextlader, einen Klassenlader-Übertragungsmechanismus. Da der Klassenlader in den privaten Daten des Threads gespeichert ist, kann der Klassenlader, sobald der Thread-Kontextlader festgelegt ist, herausgenommen und bei der nachfolgenden Ausführung des Threads verwendet werden, solange es sich um denselben Thread handelt. Daher erstellt Tomcat für jede Webanwendung einen WebAppClassLoader-Klassenlader und legt den Threadkontextlader im Thread fest, der die Webanwendung startet. Auf diese Weise holt Spring den Threadkontextlader beim Start heraus, um die Bean zu laden. Der Code zum Laden des Spring-Threadkontexts lautet wie folgt:

cl = Thread.currentThread().getContextClassLoader();

In der Startmethode von StandardContext wird der Kontextlader des aktuellen Threads auf WebAppClassLoader eingestellt.

Am Ende der Startmethode wird der Kontextlader des Threads wiederhergestellt:

Thread.currentThread().setContextClassLoader(originalClassLoader);

Warum ist das so?

Der Thread-Kontextlader ist eigentlich ein privater Thread-Datensatz, der an den Thread gebunden ist. Nachdem der Thread den Start der Kontextkomponente abgeschlossen hat, wird er in den Thread-Pool zurückgeführt und dann für andere Aufgaben verwendet. Um andere Aufgaben nicht zu beeinträchtigen, muss der vorherige Thread-Kontextlader wiederhergestellt werden.
Priorisieren Sie das Laden der Web-Anwendungsklasse und ändern Sie sie nach Abschluss des Ladevorgangs wieder auf die ursprüngliche Klasse zurück.

Der Thread-Kontextlader gibt den Unterklassenlader an, um eine bestimmte Bridge-Klasse zu laden, beispielsweise den JDBC-Treiber.

Zusammenfassen

Die Tomcat Context-Komponente erstellt für jede Webanwendung einen WebAppClassLoader-Klassenlader. Da die von verschiedenen Klassenladerinstanzen geladenen Klassen voneinander isoliert sind, wird der Zweck der Isolierung von Webanwendungen erreicht. Gleichzeitig werden JAR-Pakete von Drittanbietern über übergeordnete Lader wie CommonClassLoader gemeinsam genutzt. Wie lädt ein gemeinsam genutztes JAR-Paket eines Drittanbieters Klassen für eine bestimmte Webanwendung? Dies kann durch das Einstellen des Thread-Kontextladers gelöst werden.

Von mehreren Anwendungen gemeinsam genutzte Java-Klassendateien und JAR-Pakete werden in den vom Webcontainer angegebenen gemeinsamen Verzeichnissen abgelegt:

Allgemeiner ClassLoader
Entspricht <Tomcat>/common/*

CatalinaClassLoader
Entspricht <Tomcat >/server/*

SharedClassLoader
Entspricht <Tomcat >/shared/*

WebAppClassloader
Entspricht <Tomcat >/webapps/<app>/WEB-INF/*

Sie können die Ladepfade verschiedener Klassenlader in der Datei Catalina.properties im Tomcat-Verzeichnis „conf“ konfigurieren.

Wenn ein ClassNotFound-Fehler auftritt, sollten Sie überprüfen, ob Ihr Klassenlader korrekt ist.
Der Thread-Kontextlader kann nicht nur in Tomcat- und Spring-Klassenladeszenarien verwendet werden, sondern auch, wenn die Kern-Framework-Klasse bestimmte Implementierungsklassen laden muss. Beispielsweise lädt das uns bekannte JDBC verschiedene Datenbanktreiber über den Kontextklassenlader.

Dies ist das Ende dieses Artikels darüber, wie Tomcat den übergeordneten Delegationsmechanismus unterbricht, um isolierte Webanwendungen zu erreichen. Weitere relevante Inhalte zu isolierten Tomcat-Webanwendungen finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Lösung für die hohe CPU-Auslastung des Tomcat-Prozesses
  • SpringBoot startet eingebettete Tomcat-Implementierungsschritte
  • Eine kurze Erläuterung, wie Tomcat den übergeordneten Delegationsmechanismus unterbricht
  • Verwenden Sie Tomcat, um die gemeinsam genutzte Bibliothek so einzurichten, dass sie dasselbe JAR teilt.
  • Fünfzehn Tomcat-Interviewfragen, eine seltene Gelegenheit!

<<:  Sechs Tipps zur Verbesserung der Ladegeschwindigkeit von Webseiten

>>:  So lösen Sie das Problem des ungültigen linken Joins in MySQL und die Vorsichtsmaßnahmen bei seiner Verwendung

Artikel empfehlen

MySQL 5.7.19 neueste Binärinstallation

Laden Sie zunächst die Zip-Archivversion von der ...

Detaillierte Schritte zur Installation von MySql 5.7.21 unter Linux

Vorwort Die am häufigsten verwendete Datenbank in...

Umfassendes Verständnis der HTML-Grundstruktur

Einführung in HTML HyperText-Auszeichnungssprache...

So passen Sie Docker-Images mit Dockerfile an

Anpassen von Bildern mit Dockerfile Unter Bildanp...

Erstellen Sie mit Node.JS ein Echtzeit-Warnsystem für Unwetter

Inhaltsverzeichnis Vorwort: Schritt 1: Finden Sie...

Tutorial zur Oracle-Bereitstellung in einer Linux-Umgebung

1. Umgebung und zugehörige Software Virtuelle Mas...

Beispielcode für die HTML-Formatierung von JSON

Ohne weitere Umschweife werde ich den Code direkt...

So zeigen Sie den Rahmen an, wenn td leer ist

Zuvor habe ich zusammengefasst, wie man mit CSS di...

XHTML-Tutorial für die ersten Schritte: XHTML-Webseiten-Bildanwendung

<br />Das sinnvolle Hinzufügen von Bildern k...

Tutorial zum Importieren und Exportieren von Docker-Containern

Hintergrund Die Popularität von Docker hängt eng ...

So lassen sich Python-Skripte direkt unter Ubuntu ausführen

Nehmen wir als Beispiel das Übersetzungsprogramm....

Detaillierter Prozess zum Upgrade von gcc (Version 10.2.0) in der CentOS7-Umgebung

Inhaltsverzeichnis Kurze Einleitung 1. Überprüfen...