Entwurf und Implementierung eines Frameworks für Profiling- und Performancemessungen mit Hilfe von aspektorientierter Programmierung (AOP)


Masterarbeit, 2004

149 Seiten, Note: 1.0


Leseprobe


Inhaltsverzeichnis

1 Einleitung
1.1 Der Lebenszyklus einer Anwendung
1.2 Ziel dieser Arbeit

2 Übersicht
2.1 Pro ling-Methoden
2.2 Aspektorientierte Programmierung
2.3 Framework PerfLoad
2.4 PerfLoad und AOP

3 Pro ling-Methoden
3.1 Übersicht existierender Systeme . .
3.2 JMX
3.3 JVM Interfaces
3.4 Bytecode Modi kation

4 Aspektorientierte Programmierung
4.1 AspectJ
4.2 AspectWerkz
4.3 JBossAOP
4.4 Weitere Ansätze
4.5 Zusammenfassung

5 Das Lasttest-Framework PerfLoad
5.1 Vorhandene Lasttest-Frameworks .
5.2 Grundstruktur von PerfLoad
5.3 Komponenten von PerfLoad
5.4 Testerstellung
5.5 Auswertung der Testergebnisse . .

6 AOP für Pro ling
6.1 Zusammenarbeit der Aspekte mit PerfLoad .
6.2 Kollektor-Prozess
6.3 Managementkonsole
6.4 EJB-Aspekt

4 INHALTSVERZEICHNIS

6.5 Web-Aspekt

7 Performancevergleich
7.1 Manuelle Codierung vs. AspectJ .
7.2 AspectJ vs. AspectWerkz
7.3 Zusammenfassung

8 Kon guration
8.1 AspectJ
8.2 AspectWerkz O ine
8.3 AspectWerkz Online
8.4 Zusammenfassung

9 Fazit

A Übersicht weiterer Pro ler

B AspectJ Kurzreferenz
B.1 Aspekte
B.2 Pointcut De nitionen
B.3 Advice Deklaration
B.4 Spezielle Datentypen innerhalb von Advices
B.5 Primitive Pointcuts

C AspectWerkz Kurzreferenz
C.1 Join Point Auswahlsprache
C.2 Deployment models
C.3 Advice Deklaration
C.4 Pointcut De nition

D CD Inhalt

E Quellcode

F Verwendete Anwendungen

G Verwendete Bibliotheken

Abbildungsverzeichnis

2.1 Übersicht Pro ling-Methoden

2.2 Architektur von PerfLoad

3.1 Übersicht JMX

3.2 Übersicht JVMPI

3.3 Übersicht JSR 163

3.4 Transformation einer Klasse

3.5 Möglichkeiten, den Ladevorgang zu beein ussen

4.1 Modularisierung durch AOP

4.2 Einweben der Aspekte in AspectJ

4.3 call und execution bei AspectJ

4.4 Native Hotswap

5.1 Architektur von The Grinder

5.2 Grundstruktur PerfLoad

5.3 Informationskonsole auf dem Dämon-Rechner

5.4 Managementkonsole während eines Testlaufs .

5.5 Dämonfenster mit Statusinformationen

5.6 Testlauf mit 27 virtuellen Clients

5.7 Verteilungsdiagramm mit 3 Messpunkten

6.1 Architektur der Messwerterfassung

6.2 Modi der Messwerterfassung

6.3 Menüpunkte für Messungen ohne Clients

6.4 Gesamtarchitektur von PerfLoad

7.1 Manuelle Codierung vs. AspectJ

7.2 Messpunkte in Szenario 1

7.3 Architektur Dukes Bank

8.1 Kon gurationsablauf AspectJ

8.2 Kon gurationsablauf AspectWerkz O ine

8.3 Kon gurationsablauf AspectWerkz Online

D.1 CD-Inhalt

Tabellenverzeichnis

7.13 Messergebnisse Szenario1 - 1 Client : J2EE Referenzcontainer

7.14 Messergebnisse Szenario1 - 16 Clients : J2EE Referenzcontainer

7.15 Messergebnisse Szenario1 - 1 Client : OC4J

7.16 Messergebnisse Szenario1 - 16 Clients : OC4J

7.17 Messergebnisse Szenario1 mit Parameteraufrufen

7.20 Messergebnisse Szenario2 - 1 Client : OC4J

7.21 Messergebnisse Szenario2 - 9 Clients : OC4J

Eidesstattliche Erklärung

Hiermit erkläre ich, dass ich diese Masterarbeit selbstständig verfasst und noch nicht anderweitig zu Prüfungszwecken vorgelegt habe.

Ich habe weiterhin keine anderen Quellen oder Hilfsmittel benutzt, als die angegebenen. Alle wörtlichen und sinngemäÿen Zitate habe ich im Text entsprechend als solche gekennzeichnet.

Ort, Datum Michael Dempfle

Zusammenfassung

Aspektorientierte Programmierung (AOP) ist ein Ansatz, Funktionalitäten zu kapseln, die an vielen Stellen einer Anwendung auftreten. Für die Programmierung dieser sogenannten Crosscutting Concerns sind mehrere Implementierungen auf den Markt gekommen, welche sehr unterschiedliche Ansätze verfolgen. Bis jetzt wird AOP jedoch in realen Projekten noch nicht sehr häu g eingesetzt. Diese Masterarbeit verfolgt das Ziel, ein Framework zu entwickeln, um AOP für die Messpunktsetzung in bereits laufenden Anwendungen zu verwenden. Um eine Aussage tre en zu können, ob AOP dafür eingesetzt werden kann, sind folgende Punkte zu klären:

1. Ist AOP ein guter Ansatz, mit dem existierende Anwendungen mit geringem Aufwand instrumentiert werden können?
2. Welche der existierenden AOP-Ansätze ist am besten für diesen Zweck geeignet?

Unter dem Namen PerfLoad ist ein Lasttest-Framework entworfen und implementiert worden, welches man einfach, exibel und zentral kon gurieren kann. Es bietet eine Managementkonsole, mit der die Lasttests gestartet, verwaltet und die Ergebnisse ausgewertet werden können. Für die Messpunktsetzung verwendet PerfLoad AOP. Es wurde damit untersucht, welcher der AOP-Ansätze am Besten geeignet ist, um Anwendungen gezielt instrumentieren zu können.

Um eine Aussage tre en zu können, ob AOP überhaupt sinnvoll für die Messpunkt- setzung verwendet werden kann, wurden die existierenden Methoden (JMX, JVMPI und Bytecode-Manipulation) untersucht, mit deren Hilfe Informationen aus einem lau- fenden System gewonnen werden können. Dabei wurde festgestellt, dass diese Methoden für bestimmte Aufgaben gut geeignet sind, jedoch immer auch Nachteile besitzen, die eine uneingeschränkte Benutzung in allen Phasen der Entwicklung nicht ermöglichen.

Die Untersuchung der beiden Java-basierenden AOP-Ansätzen AspectJ und Aspect- Werkz hat gezeigt, dass diese ausreichende Möglichkeiten bieten, die für Messpunkt- setzung benötigte Bytecode-Modi kation auch ohne teure Speziallösungen und ohne groÿen Aufwand durchzuführen. Beide Lösungen erzeugen im Verhältnis zu einer hand- codierten Variante nur einen geringen Overhead und sind deswegen sehr gut geeignet, Instrumentierung von Anwendungen einfach, schnell und e zient durchzuführen.

Zum Schluss war noch die Frage zu klären, welcher der AOP-Ansätze am besten für die Verwendung bei Lasttests geeignet ist. Zunächst wurde die Performance als wichtigstes Kriterium untersucht. Hierbei hat sich gezeigt, dass die Geschwindigkeits- unterschiede in einem realen Szenario sehr klein waren. So wurde zusätzlich noch der Kon gurationsaufwand und der Funktionsumfang für die endgültige Beurteilung berücksichtigt.

AspectJ bietet die meisten Möglichkeiten, Messpunkte zu setzen, ist auf allen getesteten Servern problemlos einsetzbar und hat auch eine gute Toolunterstützung, welche die De nition der Messpunkte deutlich einfacher macht. AspectWerkz ist dagegen bei Lasttests etwas performanter und die Kon guration ist im Online Modus mit dem wenigsten Aufwand verbunden.

Obwohl AspectWerkz für die Messpunktsetzung bei Lasttests leichte Performance und Kon gurationsvorteile zeigte, ist die Entscheidung letztlich für AspectJ gefallen, da hier der Stand der Entwicklung, die Serverunabhängigkeit, die Möglichkeiten der umfangreichen Messpunktsetzung und die bereits vorhandene Unterstützung von Ent- wicklungsumgebungen ein schnelleres und problemloseres Arbeiten ermöglicht.

Jedoch kann man von AspectWerkz noch einiges erwarten. So sind zurzeit zwar noch einige Einschränkungen und Fehler in der Implementierung enthalten, jedoch darf man nicht vergessen, das dieses Projekt erst in der Version 0.9 verfügbar ist und meiner Meinung nach noch sehr viel mehr Potential darin steckt.

Vorwort

Ich möchte mich bei der Firma MGM EDV-Beratung dafür bedanken, dass Sie mich dabei unterstützt hat, meinen Master machen zu können. Vor allem die exible Arbeits- zeit hat es mir ermöglicht, dieses Vollzeitstudium parallel zu meiner normalen Arbeit durchzuführen.

Auch möchte ich allen Verantwortlichen der FH-Nürnberg meinen Dank aussprechen, da ein Stundenplan gefunden werden konnte, um Arbeit und Studium unter einen Hut zu bringen. Vor allem Herr Prof. Dr. Riekeheer und mein Betreuer Herr Prof. Dr. Knebl haben sich immer wieder Zeit genommen, um mich zu unterstützen.

Vielen Dank auch an Martin Backschat, da mit ihm die Idee entstand, dieses Thema genauer zu untersuchen. Er hat vor allem am Anfang der Arbeit dazu beigetragen, diese in die richtige Richtung zu lenken. Ebenfalls bedanken möchte ich mich bei Silke Schmidt, Karl-Wilhelm Schick, Christian Ey und Jutta Sohili für die gewissenhafte Korrektur dieser Arbeit.

Kapitel 1

Einleitung

Die Anforderungen, die heutzutage an Software gestellt werden, haben sich in den letzten Jahren in vielerlei Hinsicht geändert. Mit der Web-Technologie wird seit Ende der 90-er Jahre ein immer gröÿer werdender Anteil an Server-zentrierten Internet- und Intranet-Anwendungen entwickelt, die oft eine hohe Anzahl von Benutzern haben und auf groÿe Datenmengen zugreifen.

In der Entwicklung werden in vielen Firmen zwar Funktionstests durchgeführt, je- doch wird in den seltensten Fällen bereits in frühen Phasen das System daraufhin untersucht, wie sich die einzelne Module bzw. die gesamte Anwendung unter Last verhalten. Anwendungen, die schon im produktiven Einsatz sind, bekommen oft Per- formanceprobleme, wenn plötzlich die Anzahl der Benutzer stark zunimmt oder sich die Datenmengen, die übertragen werden bzw. sich in den Datenbanken be nden, ver- gröÿern.

Eine Anwendung kann in der Entwicklungs- und Testphase sehr stabil und schnell laufen, aber dennoch in der Produktionsumgebung nicht entsprechend skalieren. Per- formanceprobleme können im produktiven Betrieb durch eine Vielzahl nicht vorherseh- barer Faktoren hervorgerufen werden. Darum ist es wichtig, den Ein uss der Infrastruk- tur, in der die Anwendung läuft, und das Verhalten, wie sich die vielen verschiedenen Anwendungskomponenten unter Last gegenseitig beein ussen, zu verstehen.

Zur Diagnose ist es wichtig, ein Performanceproblem Schritt für Schritt eingrenzen und so bis an die Wurzel zurückverfolgen zu können. Hierbei benötigt man Mechanismen, um zunächst die Schicht in der Anwendungsarchitektur, dann die Anwendungskomponente und zum Schluss das verantwortliche Codestück zu isolieren.

Performancekritische Faktoren in Bezug auf den produktiven Einsatz liegen auch in den Bereichen Auslieferungen und Management der Anwendungen. So ist oftmals keine ausreichende Kommunikation zwischen der Entwicklung, der Qualitätssicherung und dem Support-Team vorhanden, welches die Anwendung verwaltet. Es gibt groÿe Rechenzentren, die viele hunderte Anwendungen ohne tieferes Wissen betreiben und somit Problemstellen sehr schwer identi zieren können.

Oft ist auch bei der Architektur der Software zu wenig auf Performance und Ska- lierbarkeit geachtet worden. In späteren Entwicklungsstadien ist es dann meist nur mit sehr groÿem nanziellen Aufwand möglich, eine performante Lösung zu nden.

Aufgrund des enormen Zeitdrucks bei vielen Projekten werden Anwendungen oftmals ohne ausreichende Lasttests ausgeliefert, welche Skalierungs- und Leistungsschwächen rechtzeitig aufdecken würden.

Die Ursache für ein Performanceproblem in einer komplexen, verteilten und dynamischen J2EETM(Java 2 Enterprise Edition) Umgebung [1] zu nden, ist somit eine echte Herausforderung.

1.1 Der Lebenszyklus einer Anwendung

Im Lebenszyklus einer Anwendung gibt es viele Personen, die für die Leistung des Systems verantwortlich sind: Software-Architekten, Entwickler, die Qualitätssicherung und ein Admin-Team, welches die Anwendung in der Produktion betreut. Sie alle haben Anforderungen an eine Leistungsanalyse, aber durch die verschiedenen Umgebungen, in denen sie arbeiten, sehr unterschiedliche Möglichkeiten, das System zu beein ussen:

- In der Designphase sind Skalierbarkeit und Performance wichtige Kriterien, die oftmals über den Erfolg eines Projekts entscheiden. Dieser Bereich wird in die- ser Arbeit nicht weiter beleuchtet, da in dieser Phase keine Testtools verwendet werden. Interessierte können in [2], [3] oder [4] Informationen zu diesem Thema erhalten.
- In der Entwicklungsphase können Testprogramme sehr sinnvoll eingesetzt wer- den, um Performance und Funktionalität zu testen. Entwickler sollten in diesem Zeitraum die einzelnen Komponenten nach Kriterien wie Latenz und Ressourcen- nutzung untersuchen.
- In der Qualitätssicherungsphase werden typischerweise Funktionstests des gesam- ten Systems und anschlieÿend Lasttests durchgeführt. Die vollständige Anwen- dung sollte mit allen Schnittstellen zu externen Systemen vor dem Release der Software einem Lasttest unterzogen werden. Besonderes Augenmerk muss vor allem darauf gelegt werden, dass die zu erwartende Last auch in der zu erwar- tenden Umgebung erzeugt wird. Dabei sollten die einzelnen J2EETM Schichten bis hinunter zu den einzelnen Methoden untersucht werden. Dies kann mit so genannten Pro lern geschehen, welche Daten mit unterschiedlichsten Methoden (siehe Kapitel 3) direkt aus der laufenden Anwendung gewinnen können. Pro lingtools aus der Entwicklungsphase können während eines Lasttests wegen ihres groÿen Overheads in der Qualitätssicherung nicht verwendet werden. Des- wegen müssen solche Diagnoseanwendungen in dieser Phase speziell für diesen Zweck ausgelegt und optimalerweise in ein Lasttestsystem eingebettet sein. In diesem Bereich liegt auch der Fokus des Frameworks, das in dieser Arbeit entwickelt wurde.
- In Produktivsystemen ist es wichtig, die Anwendung permanent zu überwachen, um im Fehlerfall das Problem schnell einzugrenzen und beheben zu können. Hier ist der Einsatz von Monitoring-Systemen sinnvoll, welche festgelegte Parameter überwachen und protokollieren. Es ist manchmal schwierig, Probleme aus der Produktivumgebung in Testumgebungen nachzustellen. Deswegen ist eine gewisse Analysefähigkeit im Produktivsystem sehr wichtig.

Ein komplettes Analysepaket sollte alle Bereiche im Lebenszyklus einer Anwendung abdecken, um Performanceprobleme erkennen zu können. Doch es wird sich hier nie um eine einziges Tool handeln, denn je nach Phase müssen verschiedene Möglichkeiten bereitgestellt werden, um die gewünschten Messwerte zu bekommen. Diese werden in dieser Arbeit im Kapitel 3 Pro ling-Methoden detailliert dargestellt und analysiert.

1.2 Ziel dieser Arbeit

Es gibt bereits viele verschiedene Ansätze, Messungen in einer J2EE Umgebung durchzuführen. Diese haben jedoch meist einen groÿen Overhead oder sind proprietäre[1] Speziallösungen, die Firmen für ihre eigenen Produkte entwickelt haben.

Ziel dieser Masterarbeit ist es, ein Verfahren zu entwickeln, das J2EE Systeme mit möglichst wenig Overhead und maximaler Flexibilität für Messungen instrumentieren und unter Last testen kann. Dabei sollte dieses Verfahren die Hauptschwächen vorhandener Pro ler eliminieren: Erzeugung unnötiger CPU-Last und die Ermittlung von nicht benötigten Informationen, welche herausge ltert werden müssen und somit weitere Performanceverluste erzeugen.

Grundidee ist der Einsatz aspektorientierter Programmierung (AOP) im Bereich der Lasttestmessungen. Aspekte sind in diesem Zusammenhang Codestücke, die an beliebigen Stellen im Programm eingebunden werden können. Dieser Ansatz soll ver- wendet werden, um Messpunkte in die vorhandene Anwendung einzuweben. So wird die Anwendung mit dem gewünschten Code angereichert und Messdaten damit gewonnen.

Dieser Ansatz ist bisher noch nicht speziell für den Einsatz zur Messpunktsetzung bei Lasttests verwendet worden. Die Arbeit soll den Aufwand, den Nutzen und die Möglichkeiten dieser Lösung für solche Messungen klären.

Für die Performance-Messungen müssen Messpunkte in eine bestehende J2EE-An- wendung eingefügt werden, ohne den Quellcode dieser Anwendung zu verändern. Die Messpunkte sollen exibel de nierbar, einfach veränderbar und erweiterbar sein. Dazu werden verschiedene Ansätze aspektorientierter Programmierung (AOP) untersucht, um das optimale Verfahren auszuwählen. Ziel ist es, alle benötigten Informationen aus einem laufenden System mit minimalem Overhead zu gewinnen. Dabei werden die verschiedenen Aspekte Schritt für Schritt in verschiedenen Testszenarien entwickelt, um das Verhalten des J2EE Systems zu testen.

Um dies zu realisieren, wird ein Framework entwickelt und implementiert, welches eine Clientverteilung auf verschiedene Rechner ermöglicht. Diese Clients werden über [1]Man bezeichnet im Computerbereich traditionell Dateiformate, Protokolle usw. als proprietär, die nicht allgemein anerkannten, herstellerübergreifenden Standards entsprechen, also sozusagen hauseigene Entwicklungen sind.

einen Masterprozess von einem Rechner aus gesteuert. Die Messungen innerhalb der Anwendung sollen mit Hilfe von AOP durchgeführt und die Messdaten vom Framework verarbeitet werden. Das zu entwickelnde Framework soll möglichst frei kon gurierbar und die komplette Administration zentral verwaltbar sein.

Kapitel 2

Übersicht

In dieser Masterarbeit wurde das Framework PerfLoad (Performance and Loadtest) entwickelt, welches als exibles und unabhängig einsetzbares Lasttestsystem für Server- basierte J2EE-Anwendungen verwendet werden kann. Dabei wurden zuerst existierende Tools untersucht, um die Anforderungen zu kennen, die solche Systeme erfüllen müssen. Vor allem ist es wichtig, deren Einschränkungen und Ansätze zu ermitteln, damit in der Konzeptionsphase ein optimales Design gewählt werden kann. Es werden zwei Arten von Programmen, benötigt, um Performancemessungen durchzuführen:

1. Tools zur Lasterzeugung und
2. Tools um Messungen im System durchzuführen.

Es existieren Kombinationen der beiden, jedoch kann man diese unabhängig vonein- ander betrachten, da die Erzeugung der Last nichts mit den Messungen selbst zu tun hat.

Pure Lasterzeugungssysteme, wie z. B. JMeter [5] und The Grinder [6], welche spä- ter im Abschnitt 5.1 noch genauer vorgestellt werden, liefern nur Messergebnisse von der Clientseite. Diese spiegeln die Antwortzeiten des Servers wider, wie sie am Client gemessen werden. Das sind sehr wichtige Daten, da der Benutzer des Systems diese Zeiten direkt zu spüren bekommt. Ein erster Lasttest mit solchen Tools ist meist der erste wichtige Ansatzpunkt um das Verhalten einer Anwendung unter Last herauszu n- den. Wenn in dieser Testphase die gewünschten Reaktionszeiten vorhanden sind, wer- den meist weitergehende Untersuchungen nicht mehr durchgeführt. Sind tiefergreifende Untersuchungen notwendig, ist meist der Einsatz von Pro lern nötig. In Abschnitt 3.1 werden einige der wichtigsten existierenden Pro ler-Systeme kurz vorgestellt.

Das in dieser Arbeit entwickelte Lasttestsystem ist eine Kombination aus Lasterzeu- gungsanwendung und Pro ler. Es ermöglicht komplette Untersuchungen einer J2EE- basierten Anwendungslandschaft durchzuführen. Bevor mit der eigentlichen Entwick- lung begonnen werden konnte, mussten zunächst die vorhandenen Pro ling-Methoden untersucht werden, um später eine Aussage machen zu können, ob die Messpunktset- zung mit AOP wirklich ein sinnvolles Einsatzgebiet dieser neuen Technologie ist.

2.1 Pro ling-Methoden

Zurzeit gibt es drei verschiedene Möglichkeiten (siehe Abbildung 2.1), um Messdaten aus J2EE Anwendungen zu gewinnen:

1. Java Management Extension (JMX)
2. Java Virtual Machine Pro ling Interface (JVMPI)
3. Bytecode Modi kation

Abbildung in dieser Leseprobe nicht enthalten

Abbildung 2.1: Übersicht Pro ling-Methoden

Die JMX Schnittstelle (siehe 3.2) [13] ist eine einfache Möglichkeit, Anwendungen zu überwachen, da diese bereits von vielen Applikationsserverherstellern bereitgestellt wird. An der JMX-Schnittstelle können Messwerte abgegri en werden, die von den Entwicklern des Servers und der Anwendung festgelegt werden. Eine Veränderung der Messpunkte ist durch Kon guration des Testsystems somit nicht möglich. Diese Werte sind meist Statusinformationen und können sehr gut dafür verwendet werden, um ein System ohne groÿen Overhead zu überwachen. Zum Beispiel kann bei dem Servlet- Container Tomcat die aktuelle Anzahl der Sessions abgefragt werden. Der Nachteil dieses Ansatzes ist, dass tiefere Diagnosen aufgrund der fest vorgegebenen Messpunkte nicht möglich sind.

Die zweite Möglichkeit ist die Verwendung der Schnittstelle JVMPI (siehe 3.3.1) [14], die die Laufzeitumgebung von JavaTM (JVM) bereitstellt. Viele Pro ler verwen- den dieses Interface, da hier sehr detailliert und dynamisch Daten ausgelesen werden können. Vor allem für Entwickler sind diese Informationen sehr interessant, da diese Zugri smöglichkeit bis auf Methodenebene verfügbar sind und sogar Transaktionsver- folgung möglich ist. Dadurch sind aber auch sehr viele Daten vorhanden, welche nicht benötigt und somit weggeworfen werden. Aus diesem Grund wird diese Methode sel- ten für Lasttests und in der Produktion eingesetzt, sondern für das Feststellen von Blockierungen, Optimierungsmöglichkeiten der Programmierung usw. verwendet.

Ab JDK 1.5 soll es noch zwei weitere Möglichkeiten geben, J2EE Anwendungen zu überwachen. JSR[1] 163 [22] (siehe 3.3.2) und JSR 174 [23] (siehe 3.3.3) sind zwei Spezi kationen, die festlegen, wie über eine Schnittstelle der JVM gezielt Informationen aus dem laufenden System gewonnen werden können.

Als dritter Mechanismus steht die Instrumentierung des Bytecodes (siehe 3.4) zur Verfügung. Diese Methode wird meist von Herstellern für Diagnoseanwendungen in späteren Phasen des Lebenszyklus einer Software verwendet. Hier gibt es verschiedene Techniken um ein ausgeglichenes Verhältnis zwischen Detailinformationen und Over- head herzustellen:

- Man kann man stichprobenartig einen Teil der auftretenden Ereignisse heraus- ltern, um die Anwendung so wenig wie möglich zu beeinträchtigen. Das so ge- nannte Sampling hat den Nachteil, dass man Events, die nur unregelmäÿig oder nur bei einer bestimmten Reihenfolge auftreten, nicht erkennen kann.
- Eine Aggregation[2] genannte Technik protokolliert und kombiniert eine Sequenz von Ereignissen und hält diese als einen einzelnen Wert - wie zum Beispiel einem Durchschnitt - fest. Man kann so sehr schnell eine Übersicht und eine Eingrenzung des Problems gewinnen, jedoch ist eine genaue Diagnose nicht möglich, da der einzelne Wert, wie der eines Übergabeparameters, mit dieser Methode nicht mehr ermittelt werden kann.
- Es können alle Ereignisse aufgezeichnet werden, um möglichst viele Informationen zu gewinnen. Diese Vorgehensweise bietet die meisten Details, um Probleme mit langsamen Methoden, Abhängigkeiten von Übergabeparametern, Speicher oder Synchronisierung zu erkennen und zu beheben. Sie bringt aber wieder sehr viel Overhead mit sich und sollte deswegen intelligent eingesetzt werden. Der Fehler kann zunächst grob eingegrenzt und dann weiter lokalisiert werden, indem das Überwachungsnetz immer enger gezogen wird.

Bei der Bytecode-Modi kation gibt es drei verschiedene Zeitpunkte, wann diese durchgeführt werden können:

- Statisch
- Beim Laden der Klasse
- Dynamisch

Im Kapitel 3 werden die vorgestellten Möglichkeiten detailliert untersucht. Es wird beschrieben, wie diese funktionieren und welche Informationen damit gewonnen werden können. Vor allem die Vor- und Nachteile der jeweiligen Pro ling-Methode und deren Einsatzgebiete werden dort genau erläutert.

Die Analyse der vorhandenen Pro ling-Methoden zeigt, das JMX zu statisch ist und JVMPI zu viel Overhead erzeugt, um sinnvoll für Lasttests eingesetzt werden zu können. Bytecode Modi kation ist der richtige Ansatz, um Messpunkte gezielt und exibel in einer Anwendung setzen zu können. Jedoch verwenden bis jetzt alle Hersteller, die Bytecode verändern, hausinterne Lösungen, um diese Art der Erweiterungen durchzuführen.

Existierende AOP-Ansätze benutzen auch die Bytecode-Modi kation. Jedoch verwenden die Implementierungen einen sehr generischen Ansatz, um die Modi kationen durchzuführen und sind deswegen sehr exibel einsetzbar.

2.2 Aspektorientierte Programmierung

Einsatzfähige AOP-Implementierungen sind erst seit relativ kurzer Zeit verfügbar und scheinen sehr gut dafür geeignet zu sein, den Anwendungscode zu instrumentieren. Deswegen werden die vielversprechendsten AOP-Ansätze AspectJ, AspectWerkz und JBossAOP vorgestellt (siehe 4.1, 4.2 und 4.3) und vor allem auf Funktionsumfang, Performance und Kon guration untersucht.

Zu Beginn des Kapitel 4 wird der Begri der aspektorientierten Programmierung ausführlich erläutert. Für diese Übersicht ist es ausreichend zu wissen, dass Aspekte Programmlogik kapseln, welche an vielen Stellen der Anwendung vorkommen können (z. B. Logging). Diese Aspekte werden über De nitionen, welche je nach verwendeter AOP-Implementierung völlig unterschiedlich aussehen, dem Anwendungscode hinzuge- fügt.

In den Abschnitten 4.1 - 4.4 wird untersucht, ob der Funktionsumfang der verschiedenen AOP-Ansätze ausreichend ist, um diese im Lasttest-Framework einzusetzen. Dafür werden die verschiedenen Aspekt-De nitionsumfänge genau untersucht. Als Ergebnis kann festgestellt werden, das AspectJ (siehe 4.1) für den Bereich der Messpunktsetzung alle erforderlichen De nitionen unterstützt und damit Messungen an allen Stellen des Systems durchgeführt werden können.

AspectWerkz (siehe 4.2) ist in dieser Hinsicht noch etwas eingeschränkt, da in der aktuellen Version (0.9) bestimmte Messpunkte noch nicht fehlerfrei auf allen Applikati- onsservern gesetzt werden können. Die zur Verfügung stehenden restlichen Konstrukte sind in den meisten Fällen ausreichend, da die nicht einsetzbaren De nitionen das Set- zen der Messpunkte oftmals nur vereinfachen. So können bei AspectJ mit einer einzigen De nition z. B. Messpunkte an allen Methoden gesetzt werden, die einen Datenban- kaufruf beinhalten. Bei AspectWerkz müssen die einzelnen Methoden bei der De nition angegeben werden (siehe 7.2.2). Alle anderen AOP-Implementierungen (siehe 4.3 und 4.4) sind zurzeit noch nicht weit genug entwickelt, um sinnvoll für Lasttests eingesetzt

2.3. FRAMEWORK PERFLOAD 23

werden zu können, da deren Funktionsumfang nicht ausreichend für Messpunktsetzung ist.

AspectJ und AspectWerkz sind aufgrund ihres Funktionsumfanges als Pro lingMechanismus für die Entwicklung eines Lasttest-Frameworks prinzipiell geeignet. Da zur Bestimmung des performanteren Ansatzes das Lasttest-Framework benötigt wird, wurde bei dessen Entwicklung darauf geachtet, dass es unabhängig von der jeweiligen AOP-Implementierung ist.

2.3 Framework PerfLoad

Es sollte ein System entstehen, welches gleichzeitig die Last erzeugt und Messungen in der Anwendung durchführt. Dazu wurden zunächst die Architekturen von JMeter und The Grinder analysiert und deren Schwächen und Stärken ermittelt (siehe 5.1.1 und 5.1.2).

Die entstandene Architektur legt Wert darauf, dass der Programmablauf während eines Testlaufes so wenig wie möglich beein usst wird, und trotzdem eine ausreichende Überwachung des Systemzustandes vorhanden ist.

Beim Entwurf des Frameworks wurde vor allem auf folgende Punkte geachtet:

- Zentrale Verwaltung: Es sollen alle Informationen und Dateien, die für die Durchführung eines Lasttests benötigt werden, zentral kon guriert und verteilt werden können. Kon gurationsparameter, Javaklassen, zusätzliche Bibliotheken usw. sollen von einer zentralen Stelle an alle beteiligten Instanzen vor dem Test- start übertragen werden.
- Minimaler Overhead: Um den Overhead während der Tests zu minimieren, werden Messdaten erst nach Testende zusammengefasst. Während eines Tests sind nur Statusinformationen vorhanden, welche abgeschaltet werden können.
- Flexible Kon guration von Clients: Die Clients, die später die Tests durch- führen, sollen unabhängig voneinander kon guriert werden können. Dadurch kann man unterschiedliche Szenarien zur gleichen Zeit ablaufen lassen und komplexe Tests möglich machen.
- Thin Clients: Die Clients sollen keine Abhängigkeiten zum eigentlichen Test haben. Dies bedeutet, dass z. B. selbst die Laufzeitumgebung, in der sie gestartet werden, dynamisch erzeugt wird.
- Überwachung: Die einzelnen Clients müssen periodisch überprüft werden kön- nen um sicherzustellen, ob diese noch korrekt funktionieren. Dadurch kann man fehlerhafte Testläufe erkennen und abbrechen.

Bei der Umsetzung wurden neben den genannten auch noch weitere Kriterien berücksichtigt, die im Abschnitt 5.2 beschrieben sind.

Abbildung in dieser Leseprobe nicht enthalten

Abbildung 2.2: Architektur von PerfLoad

Die Architektur von PerfLoad (siehe Abbildung 2.2) kann in 4 Bereiche aufgeteilt werden:

1. Managementkonsole: Die Managementkonsole ist die zentrale Verwaltungsein- heit im System. Sie liest alle für einen Test benötigten Komponenten ein und verteilt diese auf die jeweiligen Client-Rechner. Man kann die Tests auf der gra schen Ober äche starten, stoppen und auswerten. Auch ist es möglich, die Testabläufe zu editieren und den Test während der Ausführung zu überwachen. Am Testende sammelt die Konsole die Testergebnisse von den Clients (siehe Punkt 2) und dem externen Kollektorprozess ein (siehe Punkt 3) und stellt verschiedene gra sche Auswertungsmetriken zur Verfügung.
2. Dämon: Auf jedem Rechner, der für die Lasterzeugung genutzt werden soll, wird ein Dämon gestartet, welcher für die Erzeugung der Testclients zuständig ist. Er bekommt die Informationen von der Managementkonsole und startet eine ent- sprechende Anzahl von Testprozessen, welche wiederum eine bestimmte Anzahl von Testthreads erzeugen. Die Testprozesse fordern die Testinformationen vom Dämon an und initialisieren die Testthreads entsprechend. Nach der Initialisie- rungsphase warten alle Clients auf ein Startsignal vom Dämon, das er von der Managementkonsole erhält. Am Ende des Testsdurchlaufs schicken die Testclients ihre Messergebnisse an den Dämon und dieser wartet, bis die Managementkonsole die Daten abruft. Dadurch wird während des Tests keine Last auf dem Netzwerk erzeugt.
3. Externer Kollektorprozess: Der externe Kollektorprozess sammelt alle Mess- daten, die er von der Messpunktverwaltung (siehe Punkt 4) geschickt bekommt und speichert sie, bis die Daten am Testende von der Managementkonsole angefordert werden. Durch den Einsatz des externen Prozesses ist es möglich, die Verwaltung der Messdaten während des Tests von dem Testsystem auf einen anderen Rechner zu verlagern.
4. Messpunktverwaltung und Aspekte: In dem zu testenden System ist ein Sendeobjekt in Form eines Singletons[3] enthalten, welches dafür zuständig ist, die Messdaten der Aspekte zu verwalten. Ein Aspekt führt eine Messung durch und übergibt die Ergebnisse an das Singleton. Dieses speichert die Daten zunächst lokal und sendet sie bei geringer Serverbelastung an den externen Kollektorpro- zess (siehe Punkt 3). Dadurch beein usst die Messpunktverwaltung die aktuell laufende Anwendung nur minimal.

In den Kapiteln 5 und 6 ist das Framework PerfLoad und die einzelnen Design- und Implementierungsentscheidungen, die getro en wurden, genau beschrieben. Während der Entwicklung wurde für die Messwerteerfassung noch eine Implementierung mit einem stateless SessionBean getestet, welches genau so performant wie die Singleton- Lösung war. Der Kon gurationsaufwand war jedoch deutlich höher als beim Singleton, und deswegen wurde die Singleton-Lösung verwendet und weiter optimiert.

Nach der Entwicklung von PerfLoad wurde das Framework zunächst in einem Pro- jekt für die Ober nanzdirektion Bayern eingesetzt. Dabei wurden noch weitere De- tailverbesserungen eingebaut, um Testkon gurationen und Auswertungen exibler zu machen.

Bis zu dieser Entwicklungsstufe wurde AspectJ bei der Integration in das Framework verwendet, weil eine gra sche Unterstützung für Entwicklungsumgebungen vorhanden ist, und damit die Entwicklung der Aspekte vereinfacht wurde.

Zu dem Zeitpunkt, als mit der Untersuchung von AspectWerkz begonnen wurde ist die Version 0.9 RC1 verö entlicht worden. Bei diesem Release wurden selbstde nierende Aspekte (siehe 4.2.2) eingeführt, wodurch für die Messpunktsetzung fast die gleichen Möglichkeiten wie bei AspectJ entstanden sind.

2.4 PerfLoad und AOP

Um die Performance der verschiedenen AOP-Ansätze zu testen, wird zunächst ein Ver- gleich zwischen AspectJ und einer manuell codierten Lösung vorgestellt (siehe 7.1). Die Aspekt-Implementierung ist hier nur ca. 3 Prozent langsamer und somit in einer realen Anwendung vernachlässigbar. Wenn man dann berücksichtigt, dass der Aufwand den Code manuell einzufügen und zu verändern sehr hoch ist, kann als Ergebnis festgehalten werden, dass sich die AOP-Lösung sehr gut zur Messpunktsetzung eignet.

Um festzustellen, ob AspectJ oder AspectWerkz performanter ist, wurden zwei Sze- narien entworfen, welche jeweils einen anderen Kontext untersuchen. So ist Szenario 1 (siehe 7.2.1) ein Test, bei dem nur ein einziges Bean ohne externe Zugri e (z. B. Da- tenbank) verwendet wird. Das Bean besitzt drei Methoden, welche einander aufrufen und sehr wenig Logik enthalten. Dabei werden Messpunkte an allen Methodenaufru- fen gesetzt, um den maximalen Overhead, der durch die Instrumentierung ensteht, zu erzeugen. Bei den Testdurchläufen, die mit immer gröÿer werdender Last durchge- führt wurden, hat sich gezeigt, dass die Initialisierung von Aspekten bei AspectWerkz sehr teuer ist, und dieser AOP-Ansatz bei schlechtem Cachingverhalten des Applika- tionsserver langsamer ist als AspectJ. Bei vielen Beanaufrufen und gutem Caching des Containers ist AspectWerkz jedoch ca. 20 % schneller als AspectJ, da der eingewebte Code nach der Setup-Phase sehr e zient ist. Szenario 1 ist allerdings keine Anwendung, die in der Realität bei einem Lasttest instrumentiert wird. Deswegen wurde als zweites Szenario (siehe 7.2.2) die Beispielanwendung Dukes Bank aus dem J2EE Tutorial ver- wendet, um Messungen durchzuführen. Dort wurden die Hälfte der Datenbankzugri e und alle Aufrufe eines Session-Beans instrumentiert. Der Client testet in den Testläufen alle Teile der Anwendung, wobei in die Hälfte aller aufgerufenen Methoden Messpunk- te eingewebt waren. Der Overhead, der von beiden AOP-Implementierungen erzeugt wurde, war praktisch identisch, und deswegen können für Lasttests beide Ansätze glei- chermaÿen verwendet werden.

Zum Ende der Untersuchungen wurde verglichen, wie aufwändig es ist, eine ferti- ge Anwendung mit den unterschiedlichen AOP-Implementierungen zu instrumentieren (siehe Kapitel 8). Dabei ist bei AspectWerkz in der Variante, wo die Aspekte wäh- rend der Laufzeit eingewebt werden, die Kon guration am einfachsten. Jedoch muss AspectWerkz bei den Applikations- oder Servlet-Containern mit in die Kon guration eingebunden werden (siehe 4.2.3). Dies ist nicht bei allen Applikationsservern möglich (z. B. BeanTA [63]) und bedeutet einen zusätzlichen Aufwand beim Erstellen der Tests. AspectJ kann ohne Einschränkungen auf allen Plattformen und Containern verwendet werden, da alle benötigten Klassen mit der Anwendung deployed werden können.

Wenn man alle Kriterien wie Funktionsumfang, Performance und Kon guration betrachtet, ist AspectJ zurzeit für die Instrumentierung einer J2EE-Anwendung bei Lasttests die bessere Lösung und wird deswegen für das PerfLoad-Framework verwen- det.

In den nachfolgenden Kapiteln werden die hier kurz vorgestellten Ansätze und Lösungen ausführlich beschrieben.

Kapitel 3

Pro ling-Methoden

In Kapitel 2 wurden bereits die existierenden Pro ling-Methoden in einer kurzen Über- sicht dargestellt. Diese werden ab Abschnitt 3.2 genau untersucht und deren Stärken und Schwächen zusammengefasst. Im nächsten Abschnitt werden ein paar bekannte Pro ler kurz vorgestellt, um einen Eindruck über deren Funktionsumfang zu erhalten.

3.1 Übersicht existierender Systeme

Existierende Pro ler benutzen meist eine Kombination von verschiedenen Untersu- chungsmethoden, um dem Benutzer möglichst viele verschiedene Messergebnisse an- bieten zu können. Auch sind viele dieser Tools für unterschiedliche Einsatzzwecke kon- zipiert und können nicht in den verschiedenen Lebenszyklen der Software eingesetzt werden (siehe 1.1). Da die Anforderungen an die Pro ler - wie schon in Kapitel 1 be- schrieben - sehr unterschiedlich sind, sind Komplettlösungen meist eine Ansammlung von Einzelprogrammen, die eine gemeinsame Auswertungs- und Kon gurationsober ä- che besitzen.

Die nachfolgende Übersicht zeigt einige Pro ler, die zurzeit auf dem Markt verfügbar sind. Dabei sind keine Bewertungen der einzelnen Anwendungen enthalten, da dies über den Fokus dieser Arbeit hinausgeht.

- LoadRunnerTM der Firma Mecury Interactive [7] ermöglicht, das Systemver- halten und die Systemleistung von Anwendungen vorherzubestimmen. Heraus- ragend ist hier die Toolunterstützung für die J2EE-Applikationsserver aller be- kannten Anbieter (z. B. IBM, Bea, Oracle) in den einzelnen Enterprise Bereichen. Die LoadRunnerSuite besteht aus verschiedenen Echtzeit-Monitoren für Applika- tionsserver, Datenbankserver, Webserver und Netzwerk, die präzise Performance Messungen während der Lasttests durchführen.

Über den LoadRunnerController werden die Tests gesteuert und es ist z. B. auch möglich, Testläufe aufzuzeichnen und zu verändern. Alle Performancedaten des Systems werden gesammelt in einem Repository zur späteren Analyse und Aus- wertung abgelegt.

- JProbeTM und PerformaSureTM: Aus der Softwareschmiede Sitraka [8] kom- men mit JProbeTM und mit PerformaSureTM zwei Werkzeuge, die im Bereiche Pro ling und Performance sehr viele Bereiche abdecken. JProbeTM stellt eine Sammlung von Werkzeugen zur Fehlerbehebung und Aufdeckung von Performan- celöchern zur Verfügung. Mit Threadanalyzer, Memory Debugger, Coverage und Pro ler wird eine Diagnose der Anwendung und des Umfelds erstellt. Dabei lässt TM sich jedes auftretende Probleme genau nachverfolgen. Während sich JProbe TM als Werkzeug im allgemeinen JavaTM Umfeld positioniert, setzt PerformaSure die entsprechenden Ansprüche in Bezug auf das J2EE Umfeld um. Einsetzbar als Monitor, kann das gesamte Umfeld einer J2EE Applikation unter PerformanceGesichtspunkten betrachtet werden. Werden beispielsweise bestimmte Transaktionen als Flaschenhals aus ndig gemacht, erlaubt PerformaSureTM durch Visualisierung der einzelnen Transaktionsschritte das genaue Beobachten der beteiligten Komponenten und deren Verhalten.

- Introscope: Wily Solutions [9] hat mit Introscope ein System entwickelt, wel- ches mit geringem Overhead Anwendungen auf Performance untersucht. Die so genannte BlameTM Technologie erlaubt es, Bottlenecks in Servlets, EJBs, Klassen und Methoden zu nden. Dabei werden Agenten eingesetzt, welche die Anwen- dung permanent überwachen und deren Ergebnisse and den Enterprise-Manager weitergeben. So existieren z. B. SQL-Agenten, mit deren Hilfe alle Datenbankauf- rufe protokolliert werden können. Mit der Konsole kann man dann die Ergebnisse der Agenten über eine Reportingschnittstelle auswerten, über ein Webinterface anzeigen oder so aufbereiten, dass z. B. Alarme an ein anderes System gesendet werden.

Man kann Introscope auch so kon gurieren, dass ein sehr geringer Overhead entsteht und es zum Überwachen von laufenden Anwendungen eingesetzt werden kann. Dazu wird hier vor allem JMX (siehe 3.2) verwendet, da dieses von vielen Applikationsservern bereits unterstützt wird.

- JDBInsight von JInspired Ltd [10] ist ein innovatives Managementprodukt, welches darauf ausgerichtet ist, Performancetuning durchzuführen und J2EE An- wendungen zu testen, welche ihre Datenbankanbindung über JDBC herstellen. Es analysiert den Datenzugri von J2EE Komponenten und stellt deren Ablaufzei- ten, Ressourcenbenutzung und Transaktionspfade in einer übersichtlichen Aus- wertung dar. Der Unterschied zu anderen Pro ling- und Performance Tools ist, dass JDBInsight versucht, die Anwendung aus einer sequentiellen Sicht zu ana- lysieren. Die meisten anderen Produkte zeigen nur einen einfachen Aufrufbaum und stellen nicht dar, was für ein so genannter Execution Plan (Ausführungs- plan) von der Anwendung durchgeführt wird. Dort ist zwar meist bekannt, von wem die Methode aufgerufen wurde, aber nicht, in welchem Kontext. Da langsa- me Methoden oftmals von vielen Bereichen einer Anwendung aufgerufen werden und evtl. dieses Verhalten nur bei bestimmten Parametern auftritt, kann man bei JDBInsight diesen Pfad sehr gut zurückverfolgen und die Ursache lokalisieren.

- JPro ler und OptimizeitTM sind zwei Vertreter von Pro lern, die ausschlieÿ- lich das Java Virtual Machine Pro ling Interface (JVMPI) nutzen (siehe 3.3.1). Sie besitzen beide einen Pro ler-Agenten, der die Daten sammelt, und ein Fron- tend, auf dem die Daten aufbereitet werden.

JPro ler [11] hilft vor allem dabei CPU, Thread und Speicherdaten zu erhalten um Speicherprobleme zu beheben. Auch ist eine Unterstützung für viele Entwicklungsumgebungen und Applikationsserver vorhanden.

Optimizeit [12] bietet neben den normalen Pro ling-Informationen auch ein Tools namens Code Coverage, mit dem ausgewertet werden kann, wie oft State- ments im Javacode durchlaufen werden. So ist es möglich, unbenutzte Methoden aus dem Code zu entfernen oder den Programmablauf zu optimieren. Der eben- falls enthaltene Thread Debugger bietet die Möglichkeit, die Abhängigkeiten von Threads zu analysieren. Durch Testläufe kann man bestimmen, wie oft und von wem ein Thread blockiert wird, und Deadlock-Situationen können leicht erkannt werden.

Die Liste der Anbieter von Test Tool Suiten könnte noch um einige Seiten erweitert werden, da auch im Open-Source Bereich sehr viele kleinere Projekte in diesem Bereich vorhanden sind. Im Anhang A ist noch eine Liste von weiteren Pro ling-Anwendungen zu nden, die zeigt, wie viel Interesse und auch Bedarf in diesem Bereich besteht.

Eine Analyse der vorhandenen Tools hat jedoch gezeigt, dass selbst die umfang- reichsten Systeme gewisse Einschränkungen und Abhängigkeiten haben, da diese oft- mals vom zu untersuchenden Ziel abhängig sind. Es sind z. B. bei vielen der Produkten spezielle Module für einen bestimmen Applikationsserver nötig, um die Messdaten zu ermitteln oder es wird eine bestimme JVM benötigt. Die in dieser Arbeit entwickelte Lösung hat keine dieser Abhängigkeiten und ist somit auf allen Plattformen uneinge- schränkt einsetzbar.

3.2 JMX

Die Java Management Extension (JMX) Spezi kation 1.2 de niert ein Paket für J2EE 1.4 (bis J2EE 1.3 optional[1] ), welches eine Managementarchitektur und eine API bereitstellt. Zusätzlich erlaubt sie, jede auf Javatechnologie basierte Ressource zu überwachen und/oder zu kontrollieren. Eine Ressource ist in dem hier betrachteten Kontext meist eine Javaanwendung, kann aber z. B. auch alles sein, was von Java gewrapped oder erreicht werden kann. Zu diesem Zweck führt JMX ein JavaBean Model ein, wobei die Basis ein einfacher und doch hoch entwickelter und erweiterbarer Verwaltungsagent für die Java Virtual Machine (JVM) ist.

JMX de niert einen Satz von Diensten, welche helfen, Anwendungen zu verwalten und ist dabei sehr einfach zu benutzen. Es ist so möglich, den Quellcode eine Anwendung mit ein paar wenigen Zeilen Code zu instrumentieren.

Abbildung in dieser Leseprobe nicht enthalten

Im Grunde ist JMX das gleiche für Verwaltungssysteme, wie JDBC (Java Database Connectivity) [15] für Datenbanken: Es ist eine Abstraktionsschicht zwischen der Anwendung und beliebigen Managementsystemen.

3.2.1 JMX Architektur

Die JMX Architektur lässt sich in 3 Ebenen aufteilen:

- Instrumentation level

Diese Ebene ist der Anwendung selbst am nächsten. Sie besteht aus vier verschiedenen Konstrukten, die verwendet werden, um Anwendungen und Systemressourcen verwaltbar zu machen und einem Model, um Benachrichtigungen zu senden und zu empfangen. Die instrumentierten Ressourcen werden Management Beans (MBeans) genannt und liefern ein Interface, an dem die gewünschten Informationen abgerufen werden können.

- Agent level

Die mittlere Ebene der JMX Architektur wird agent level genannt. Sie enthält einen Server, um die MBeans verwalten zu können und auch verschiedene Dienste, die auf dem Server ablaufen und verschiedene Aufgaben, wie z. B. periodisch bestimmte MBeans abzufragen, durchführen. Die Kombination von einem MBeanServer, den registrierten MBeans und AgentDiensten wird typischerweise JMX Agent genannt.

- Distributed services level

Die dritte Ebene der JMX Architektur wird distributed services level genannt. Sie enthält die Middleware, welche die JMX-Agenten mit den Programmen ver- bindet, die die Javaanwendungen verwalten und/oder kontrollieren wollen. Diese Ebene kann in zwei Kategorien aufgeteilt werden: Protokoll Adapter und Connectoren.

Mit Hilfe eines Protokoll Adapters kann sich zum Beispiel ein Web-Browser zu einem oder mehreren JMX-Agenten verbinden und Daten aus den dort registrierten MBeans auslesen.

Ein Connector besteht aus zwei Teilen: einem Client Proxy und einem Server Stub. Die Serverseite läuft normalerweise bei dem JMX-Agenten, mit dem sie verbunden ist, und der Client ist in der JVM der Managementanwendung zu n- den. Aufgaben, wie Sicherheit und Serialisierung, werden von den beiden Komponenten innerhalb der Connectoren übernommen.

3.2.2 MBeans

JMX de niert vier verschiedene Typen von MBeans:

1. Standard MBean
2. Dynamic MBean
3. Open MBean
4. Model MBean

Jedes dieser MBeans stellt Metadaten in Form eines MBeanInfo -Objekts zur Verfügung. MBeanInfo de niert die Attribute, Operationen und Benachrichtigungen, die das MBean unterstützt.

Standard MBeans

Ein Standard MBean kann jedes JavaBean[2] sein, welches am MBeanServer registriert ist. Der Anwendungsentwickler de niert das MBean und das dazugehörige Management- Interface während der Entwicklungsphase. Jedes MBean muss ein Java Interface im- plementieren, welches der Namenskonvention <Klassenname>MBean entspricht. So muss zum Beispiel das MBean mit dem Klassennamen KfzModell das Interface KfzModellMBean implementieren. Dieses Interface stellt somit alle oder eine Untermenge der Methoden des eigentlichen MBeans zur Verfügung.

Wenn das MBean am MBeanServer registriert wird, erzeugt dieser ein MBeanInfo Objekt, welches die Metadaten aus dem <Klassenname>MBean bekommt. Für jede gefundene get - und set -Methode werden Attribute und Operationen für das MBean erzeugt. Für alle weiterenöentlichen Methoden werden nur Operationen generiert. Der MBeanServer benutzt die MBeanInfo um sicherzustellen, dass nur auf Attribute und Operationen des MBeans zugegri en werden kann, welche auch zur Verfügung gestellt wurden.

Standard MBeans sollten verwendet werden, wenn schon während der Entwicklung eine Unterstützung für JMX vorhanden sein soll und es unwahrscheinlich ist, das sich das Interface der zu verwaltenden Ressource ändert. Der Vorteil dieses Typs ist, dass er extrem einfach zu implementieren ist und dies parallel mit der normalen Entwicklung der Anwendung gemacht werden kann. Auch können vorhandene Anwendungen leicht zu einem MBean gemacht werden, da nur implements MBean zur Klasse hinzugefügt und ein Interface de niert werden muss.

Dynamic MBeans

Wie der Name vermuten lässt, bieten Dynamic MBeans eine exiblere Vorgehensweise an, mit dem Management-Interface zu arbeiten. So kann es der Fall sein, dass sich die Schnittstellen im Laufe der Zeit ändern. Bei der Verwendung von Standard MBeans müssten alle beteiligten Interfaces ebenfalls angepasst werden. Dynamic MBeans implementieren ein generisches Interface, welches es den Agenten möglich macht, die vorhandenen Methoden selbst zu bestimmen. Diese Vorgehensweise erlaubt es, dass die Management-Interfaces ohne Neukompilierung der Dateien verändert und die Attribute und Operationen zur Laufzeit erzeugt werden können.

Listing 3.1 Das DynamicMBean Interface

package javax.management;

public interface DynamicMBean {

public Object getAttribute( String attribute )

throws AttributeNotFoundException, MBeanException,ReflectionException; public void setAttribute( Attribute attribute )

throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException;

public AttributeList getAttributes( String[] attributes );

public AttributeList setAttributes( AttributeList attributes );

public Object invoke( String actionName, Object[] params,

String[] signature ) throws MBeanException, ReflectionExceptionn public MBeanInfo getMBeanInfo(); }

Dynamic MBeans müssen das Interface DynamicMBean (siehe Listing 3.1) imple-

mentieren. Sie beschreiben ihr eigenes Management-Interface durch das MBeanInfo Objekt, welches beim Standard MBean durch Introspection[3] vom MBeanServer generiert wird. So muss der Entwickler dafür sorgen, dass die benötigten Informationen im MBeanInfo Objekt verfügbar sind, und auch die weiteren Methoden des Interfaces DynamicMBean immer den aktuellen Stand der Klasse widerspiegeln.

Der MBeanServer fordert die MBeanInfo vom Dynamic MBean an, wann immer diese benötigt wird und delegiert Anfragen wie getAttribute() und setAttribute() direkt an das Dynamic MBean. Das MBean ist auch für die Implementierung, Validierung und den korrekten Aufruf des Interfaces verantwortlich, welches es über MBeaninfo beschreibt.

Die nächsten beiden Abschnitte beschreiben zwei standardisierte Typen von Dynamic MBeans: Open MBeans und Model MBeans.

Open MBeans

Open MBeans sind Dymamic MBeans, die nur bestimmte Datentypen zurückgeben und akzeptieren. Durch die Verwendung von speziellen Datentypen wird erreicht, dass kein Laden von zusätzlichen Klassen erforderlich ist. Dies erleichtert das deployen ei- nes MBeans in einer verteilten Systemlandschaft, da nur die Semantik der Parameter verstanden werden muss. Folgende Datentypen sind bei einem Open MBean erlaubt:

- Primitive Datentypen: int, double, boolean
- Wrapper für primitive Datentypen: Integer, Double, Boolean
- ArrayType: Ein Array von erlaubten Datentypen
- Composite: Ein Objekt, welches wieder in erlaubte Datentypen zerlegt werden kann und von der Klasse CompositeType exakt beschrieben wird Ein Open MBean muss ein OpenMBeanInfo -Objekt bei der getMBeanInfo() Methode zurückliefern. OpenMBeanInfo erweitert die Basisklasse MBeanInfo um zusätzliche Metadaten wie erlaubte Werte und Standardwerte.

Model MBeans

Ein Model MBean ist eine Erweiterung eines Dynamic MBeans. Der groÿe Unterschied ist jedoch, dass ein Dynamic MBean komplett implementiert werden muss und das Model MBean nicht. Ein Model MBean ist mehr als eine Ansammlung von Interfaces: Es ist eine anpassbare, standardisierte Implementierung des Dynamic MBeans. Jeder JMX Agent muss eine Implementierung der Klasse RequiredModelMBean haben. Dieses Model MBean ist sofort einsetzbar, da die eigene Anwendung es instanziieren und die Instanz mit seinen eigenen Verwaltungsinformationen anpassen kann. Dieser wieder- verwendbare Typ spart Zeit bei der Entwicklung und ist vor allem auch unabhängig von JVM Versionen und verschiedenen Implementierungsvarianten der JMX Agenten.

Der MBeanServer dient zum Erzeugen und Delegieren von RequiredModelMBean Instanzen. Da RequiredModelMBean von dem JMX Agenten erzeugt und verwaltet werden, kann die Implementierung dieser Klasse je nach Umgebung und verwendeter JVM unterschiedlich sein. Die Anwendung braucht sich nicht um spezielle interne De- tails, wie z. B. Persistenz, Caching und Transaktionsverhalten, zu kümmern. Dadurch wird der Code, der noch für die Instrumentierung gebraucht wird, konsistent und sehr klein.

Während der Laufzeit ist es auch möglich, dem Bean weitere Attribute hinzuzufügen, aber es ist mit seinem Standardverhalten für die Verwaltung der meisten Anwendungen schon ausreichend.

3.2.3 MBeanServer

Der MBeanServer ist die zentrale Komponente der JMX-Agent Schicht. Er läuft in der lokalen JVM ab und verwaltet die MBeans. Im Prinzip ist er eine Registrierungs- stelle für vorhandene MBeans und ein Lagerort für alle zurzeit vorhandenen MBean Namen und Referenzen, jedoch nicht zwingend ein Speicher für die MBeans selbst. Für jedes MBean werden im MBeanServer die Metadaten gespeichert, die das Verwaltungs- Interface beschreiben.

Durch die Verwendung des MBeanServers erfolgt eine Entkoppelung der Manage- ment-Anwendungen und der zu verwaltenden Ressourcen. Der Zugri auf MBeans er- folgt immer über das MBeanServer-Interface, da die MBeans über einem Objektnamen und nicht direkt referenziert werden. Dies ist ein wichtiger Punkt, da die Trennung der Ressourcen von den Verwaltungsanwendungen die Hauptaufgabe des Servers darstellt.

Weiterhin verbirgt der MBeanServer die Information, um was für ein MBean es sich eigentlich handelt. So ist es nach auÿen hin nicht ersichtlich, ob es sich um ein Standard oder Dynamic MBean handelt.

Auch können MBeans über den MBeanServer gesucht werden: Es gibt eine eigene Query-Language zum Heraus ltern von MBeans. Zum Beispiel ist es möglich, alle MBeans mit bestimmten Namen oder Attributen zu ermitteln.

3.2.4 JMX-Dienste

Der JMX-Agent de niert verschiedene Dienste, die in jedem JMX-Agenten implemen- tiert sein müssen: Den Monitoring-Service, den Timer-Service, den Relation-Service und den MBean Class-Loading-Service. Diese Dienste sind selbst MBeans, die am MBe- anServer registriert sind und bieten einige grundlegende Funktionalitäten, die vom MBeanServer, den MBeans und den Adaptern verwendet werden können. Eigene Dien- ste können dynamisch als Service-MBeans hinzugefügt werden, was den JMX Agenten exibel und erweiterbar macht. Die vorgeschriebenen Dienste sind:

- Der Monitoring-Service überprüft MBeans periodisch. Es gibt einfache vorde- nierte MBeans, die einen Zähler oder das Erkennen einer Zustandsänderung ab- fragen. So könnte z. B. die Anzahl der aktiven Sessions in einem Servlet-Container ermittelt werden.
- Der Timer-Service führt eine Operation zu einem bestimmten Zeitpunkt aus. Der Monitoring-Service benutzt diesen Dienst.
- Der Relation-Service ermöglicht es, Relationen zwischen MBeans zu verwalten. Es ist so möglich, Abhängigkeiten festzulegen und diese dann bei Abfragen zu berücksichtigen.
- Der MBean Class-Loading-Service ist dafür da, MBeans über das Netzwerk zu laden.

3.2.5 JMX-Adapter

JMX-Adapter kommunizieren zwischen den JMX-Agenten und den entsprechenden Managementsystemen. Der Adapter ist zuständig für die Übersetzung des JMX MBean Datentyps in den Datentyp, den der Manager verwendet. Somit weiÿ die externe An- wendung nicht, dass sie ihre Informationen über JMX bekommt. Für jedes Manage- mentprotokoll wird ein spezieller Adapter benötigt, um das jeweilige Managementsys- tem zu unterstützen.

Adapter sind MBeans, die am MBeanServer registriert sind. Somit ist es möglich, die vorhandenen Adapter zu nden und ihnen Benachrichtigungen bei Ereignissen zu schicken, welche diese an die Managementanwendung weiterleiten können. So kann z.

B. ein eigener JMX-Dienst bestimmte Werte überwachen und im Fehlerfall über den MBeanServer nach einem bestimmten JMX-Adapter suchen. Dieser liefert dann den ge- wünschten Adapter, und mit dessen Hilfe kann das entsprechende Managementsystem informiert werden.

Adapter und Connectoren sind in der aktuellen Spezi kation nicht de niert, jedoch gibt es viele Protokolle, für die schon Implementierungen existieren, und die zurzeit als JSR evtl. in der nächsten Version von JMX spezi ziert werden. So ist in JSR 146 Unterstützung für[4] und in JSR 70 für RMI/IIOP[5] geplant.

Für das Simple Network Management Protokol (SNMP[6] ) gibt es Implementierungen in der JMX Referenzimplementierung (JDMK[7] ) [16] von Sun und von Advnet [17]. In [18] Kapitel 9 ist ein Vergleich zwischen SNMP und JMX zu nden, welcher auÿerhalb des Rahmens dieser Arbeit liegt, aber aus Vollständigkeitsgründen erwähnt wird. In dem gleichen Kapitel ist auch ein Beispiel für einen RMI Connector für JMX enthalten.

3.2.6 Zusammenfassung

Diese kurze Übersicht über JMX hat gezeigt, wie mit einem einfachen und doch mächtigen Ansatz sehr viele Informationen aus einem System gewonnen werden können. Am einfachsten ist der Ansatz bei Applikationsservern (z. B. Websphere, JBoss) und Servlet-Containern (z. B. Tomcat, Resign) einzusetzen, da dieses Konzept schon von sehr vielen Herstellern zur internen Verwaltung verwendet wird und somit in deren Implementierungen schon viele Messpunkte vorhanden sind, die mit geeigneten Werkzeugen abgegri en werden können.

JMX ist deswegen für die Überwachung der Anwendungsumgebung sehr gut geeignet. Für die Problemsuche in Javaanwendungen sieht es da meist anders aus, da in den seltensten Fällen die Anwendung selbst für JMX vorbereitet ist. Auch für tiefergreifende Analysen ist JMX nicht geeignet, da MBeans nur festgelegte Informationen liefern, die meist nicht problembezogen sind.

Für weitere Informationen zum Thema JMX sind [18, 19, 20] sowie die JMX Spezi kation 1.2 [13] zu empfehlen.

3.3 JVM Interfaces

3.3.1 JVMPI

Übersicht

Das Java Virtual Machine Pro ling Interface (JVMPI) wurde mit dem JAVA 2 SDK eingeführt und bietet eine Möglichkeit, Performance-Messung bei Java-Anwendungen durchzuführen. JVMPI ist eine Schnittstelle, die es einem Pro ler-Agenten ermöglicht, die Java Virtual Machine (VM) zu steuern und umgekehrt der VM ermöglicht, Er- eignisse an den Pro ler-Agent zu senden. Die VM und der Pro ler-Agent laufen im selben Prozess und können somit gut miteinander kommunizieren. Durch ein Pro ler- Frontend, welcher in einem eigenem Prozess läuft, werden die Messdaten dem Benut- zer zur Verfügung gestellt. Die Kommunikation zwischen dem Pro ler-Agent und dem Pro ler-Frontend erfolgt auf Basis eines Protokolls, das zwischen den beiden Teilen individuell festgelegt werden kann. Dies stellt im Normalfall kein Problem dar, da der Hersteller einer Benutzerober äche meist den dazugehörigen Agenten mit ausliefert.

Bis zu JDK 1.4 ist die Schnittstelle allerdings noch nicht o ziell ins JDK aufge- nommen und wird voraussichtlich in JDK 1.5 durch JSR 163 und JSR 174 ersetzt. Die beiden neuen Schnittstellen werden noch genauer in den Abschnitten 3.3.2 und 3.3.3 vorgestellt.

Abbildung 3.2 zeigt eine Übersicht von JVMPI.

Die Möglichkeiten des Pro ler-Agenten beziehen sich dabei auf die Ereignisse, die

Abbildung in dieser Leseprobe nicht enthalten

Abbildung 3.2: Übersicht JVMPI

in der VM passieren und der Agent kann zur Laufzeit steuern, über welche Ereignisse, so genannte Events, er informiert werden will. Dies bietet Entwicklern von Pro lerAgenten die Möglichkeit, nur die für das Problem relevanten Events zu erhalten. So können folgende interne Aufgaben beein usst werden:

- die Steuerung des Garbage Collectors (starten, verhindern)
- Threads suspendieren; deren Status und CPU-Zeit ermitteln
- Aufrufbaum eines Threads ermitteln
- Beenden des Pro lings

Der Pro ler-Agent implementiert nur die Methode notifyEvent(). Diese Methode ermöglicht es der VM, den Pro ler-Agent über ein Ereignis zu benachrichtigen. Die Events enthalten einen Eventtyp, Informationen über den Thread, der das Ereignis ausgelöst hat und spezi sche Daten zu dem Event selbst. Um bei der Benachrichtigung so wenig Overhead wie möglich zu erzeugen, benutzt JVMPI eindeutige Bezeichner für Einheiten wie Objekte, Methoden, Klassen und Threads.

Die wichtigsten Ereignisse, die von der JVM an den Pro ler Agent geschickt werden können, sind:

- Aufruf einer Methode, Verlassen einer Methode
- Erzeugen eines Objekts und dessen Freigabe
- Starten und Beenden des Garbage Collectors
- Laden und Entladen von Klassen
- Start und Stop von Threads
- Verschiedenen Events von Javamonitoren wie wait, enter, exit
- Start und Stop der Java Virtual Machine
- Benachrichtigung, ab wann eine Klasse gepro led werden kann
- Aktionen von JIT-Compilern[8]
- Anfordern eines Speicherabbilds
- Anfordern eines Objekt Abbilds

Das Pro ler-Frontend erhält vom Pro ler-Agent relevante Informationen und bereitet diese so auf, dass die Benutzer des Pro ling-Systems damit etwas anfangen können (z. B. Gra ken erzeugen). Dabei muss das Pro ler-Frontend nicht auf dem gleichem Rechner wie die VM sein, sondern kann aufgrund des unabhängigen Protokolls auf einem anderen Rechner laufen.

Pro ler-Agenten werden bei jedem Programmstart angegeben und können somit problemlos ausgetauscht werden. Allerdings kann nur ein Pro ler-Agent pro VM gela- den werden.

Die Syntax zum Einbinden eines Agents sieht folgendermaÿen aus:

java Xrun<myprofiler> <classToBeProfiled>

<mypro ler> ist dabei der Name des Pro ler-Agents, dessen Library (mypro - ler.dll ) unter Windows im Pfad oder im bin -Verzeichnis des JAVA SDK's liegen muss. Unter Solaris muss die Datei im LD_LIBRARY_PATH mit aufgenommen werden. Beim Start lädt die VM die Pro ler-Agent-Library und holt sich durch eine Methode aus der Bibliothek einen Zeiger auf den Pro ler-Agent.

Zusammenfassung

Die JVMPI Schnittstelle ist sehr mächtig und wird von vielen Pro lern verwendet, um Informationen aus der JVM zu gewinnen. Man kann jedoch bei genauerer Betrachtung feststellen, dass diese nur so oft verwendet wird, weil noch nichts Besseres vorhanden ist. Dies wird o ensichtlich, wenn man sich die Einschränkungen der Schnittstelle genauer ansieht:

- Die Agenten sind plattformabhängig und somit sind meist nur Implementierungen für die gängigsten Betriebssysteme vorhanden.
- JVMPI ist immer noch als experimentell ausgewiesen und wird voraussichtlich nicht fester Bestandteil späterer JDKs sein.
- Es existieren viele unterschiedliche, nicht-kompatible Implementierungen, da die Schnittstelle nicht ausreichend spezi ziert wurde und keine festgelegte Testum- gebung für sie existiert. Die meisten Agenten sind deshalb JVM abhängig.
- Sie ist nicht kompatibel mit modernen Garbage Collector Mechanismen.
- Es werden Weak References[9] verwendet, welche den Garbage Collector Mecha- nismus bei groÿer Anzahl um den Faktor 3 verlangsamt.
- Die Schnittstelle hat keinen de nierten Erweiterungsmechanismus.
- Events sind in optimierten VMs sehr schwer zu warten.
- Die Informationen, die bei einem Event bekannt sind, sind sehr eingeschränkt. So muss bei einem Methodenaufruf die dazugehörige Klasse zusätzlich ermittelt werden.
- Alle registrierten Ereignisse müssen meist ge ltert werden, da z. B. nur bestimmte Methodenaufrufe interessant sind, aber Events für jeden Aufruf geschickt werden.

Diese vielen Nachteile haben dazu geführt, dass man sich in der Java Community Gedanken um einen Nachfolger dieser Schnittstelle gemacht hat, welcher im nächsten Abschnitt beschrieben wird.

3.3.2 JSR 163 - Java Platform Pro ling Architecture

Aufgrund der Probleme von JVMPI, die im vorigen Abschnitt bereits erläutert wurden, liegt für die nächste Javaversion (JDK 1.5) eine neue Spezi kation bereits vor, welche APIs festlegt, um Pro ling-Informationen aus einer laufenden JVM zu gewinnen.

Es werden Funktionen zur Messung von Ausführungszeiten und der Ermittlung des Heaps bereitgestellt. Man hat die Möglichkeit, alle Messdaten in das Ergebnis ein ieÿen zu lassen oder nur Sampling durchzuführen (siehe 2.1). Deadlocks, Speicherprobleme und langsame Methoden sollen dadurch einfacher lokalisiert und eliminiert werden können.

Die APIs sind so entworfen, dass sie Implementierungen ermöglichen, welche das System nur minimal beein ussen. Auch werden erweiterte Garbage Collection Tech- nologien unterstützt, die bei JVMPI Probleme machen. Weiterhin werden durch die neuen APIs zuverlässige Implementierungen mit vielen unterschiedlichen VMs ermög- licht, was durch Gruppierung von Funktionen in optionale Pakete erreicht wird.

Eine weitere Anforderung an die JVM ist, dass man das Pro ling dynamisch ein- und ausschalten kann. Dadurch werden Implementierungen ermöglicht, die so gut wie keinen Ein uss auf die Anwendung haben, wenn das Monitoring nicht aktiv ist.

Das primäre Einsatzgebiet dieser JSR ist die Entwicklungsphase, obwohl das Design durch seinen kleinen Overhead auch in späteren Phasen (siehe 1.1) zum Pro ling eingesetzt werden kann.

Die APIs haben zum Ziel, das experimentelle Interface JVMPI zu ersetzen und müssen deswegen vergleichbare Funktionalität bieten.

Diese Funktionalität wird auf verschiedene Interfaces aufgeteilt:

- Java Virtual Machine Tool Interface (JVMTI)
- Java Programming Language Instrumentation Services (JPLIS)
- Java Programming Language Monitoring & Management APIs

Die Java Programming Language Monitoring & Management APIs werden im JSR 174 (siehe 3.3.3) beschrieben, sind jedoch Teil des JVMTI.

Abbildung in dieser Leseprobe nicht enthalten

Abbildung 3.3: Übersicht JSR 163

JVMTI ist für Pro ling und Debugging ausgelegt und arbeitet mit einem Agenten, der plattformabhängig ist (siehe Abbildung 3.3(a)). Die Stärken von JPLIS liegen beim Highlevel-Pro ling und Monitoring, da der Agent in Java geschrieben ist. Andererseits ist JPLIS dadurch nicht so performant wie JVMTI. Jedoch hat der JPLIS-Agent Zu- gri zur Anwendung und kann diese direkt instrumentieren (siehe Abbildung 3.3(b)). Die verschiedenen Möglichkeiten, Bytecode zu verändern werden im Abschnitt 3.4 aus- führlich beschrieben.

Weiterhin de niert JSR 163 ein Technology Compatibility Kit (TCK), um vorhandene Pro ler an die neue Spezi kation anzupassen.

3.3.3 JSR 174 - Monitoring and Management Speci cation for the Java Virtual Machine

Die aktuelle JVM (JDK 1.4) besitzt keine einfache Standardschnittstelle, die Informationen über den eigenen Zustand liefert oder die Möglichkeit bietet, Parameter während der Laufzeit zu verändern.

Das Hauptziel dieser Spezi kation ist es, alle notwendigen Richtlinien und Empfeh- lungen zur Verfügung zu stellen, um APIs zu de nieren, welche es ermöglichen, die JVM zu überwachen und zu managen. Die JSR-174 schlägt keine Schnittstellen vor, sondern erwartet, dass dies an anderer Stelle gemacht wird. Die Experten der JSR-163 und JSR-174 haben sich darauf geeinigt, dass durch die Überschneidungen, die es zwischen den beiden Spezi kationen gibt, die Infrastruktur und auch die Art und Weise, wie man Daten aus der JVM gewinnt, geteilt werden: Die JSR-174 schlägt die Anforderungen vor, welche dann in der JSR-163 eingegliedert werden. JSR-163 stellt die Schnittstellen, die Referenzimplementierung und den Test Compability Kit zur Verfügung.

Weiterhin wird hier auch beschrieben, welche Anforderungen über eine Java- und welche über eine Systemschnittstelle abgebildet werden sollen. Die wichtigsten Anforderungen sind hier kurz aufgelistet und beschrieben:

- Geringer Overhead: Der Overhead soll 1 % bei gängigen Tests (specJBB, specJVM, ECPerf) nicht überschreiten.
- On-demand Monitoring, 24x7 Betrieb: Zähler und die Generierung von Ereignis- sen sollen dynamisch ein- und ausschaltbar sein. Weiterhin sollen externe Moni- tore zur Laufzeit hinzugefügt und entfernt werden können
- Multiple Management Clients Support: Parallele Überwachung von mehr als ei- nem externen Client soll möglich sein.
- Deadlock Detection Support: Ein Mechanismus und die benötigten Daten, um einen Deadlock zu erkennen, sollen bereitgestellt werden.
- Remote JVM Monitoring and Management Support: Ein Java Management Ex- tension (JMX) MBean soll bereitgestellt werden.
- SNMP Support: Eine SNMP MIB[10] soll bereitgestellt werden, um es SNMP An- wendungen zu ermöglichen, Informationen von der der JVM zu erhalten.
- JVM Data for Monitoring and Management: Hier können die verschiedensten Betriebsystem Ressourcen und Eigenschaften ermittelt werden. Zusätzlich ist es möglich, das Laden von Klassen und das Speichersystem zu überwachen.

Die vollständige Liste der Anforderungen und genauere Beschreibungen sind in [23] Part 1 - 3 enthalten.

3.4 Bytecode Modi kation

Die bis jetzt vorgestellten Möglichkeiten greifen von auÿen auf die Anwendungen zu, um Messdaten zu gewinnen. Die Bytecode Modi kation geht einen anderen Weg: Sie ändert den Code der Anwendung, die in der JVM ausgeführt wird, damit dieser die gewünschten Informationen ermittelt und über einen Mechanismus verfügbar macht. So könnte der modi zierte Code Daten in eine Datei schreiben. Im Vergleich zu den bisher behandelten Ansätzen bietet Bytecode Modi zierung folgende Vorteile:

- Der Code kann gezielt bei interessanten Paketen und Methoden erweitert werden.
- Es wird keine VM Unterstützung benötigt
- Funktioniert mit jeder Optimierung

Wegen der Vorteile benutzen bereits vorhandene Pro ler die Bytecode Modi kation, um Informationen zu gewinnen. Es handelt sich dabei aber immer um herstellerspezi sche Speziallösungen. Auch AOP beruht auf dem Prinzip der Bytecode Modi kation. Der groÿe Unterschied dazu ist jedoch, dass dieser Ansatz herstellerunabhängig ist.

Der Hauptunterschied bei den Verfahren ist der Zeitpunkt, an dem die Modi kation durchgeführt wird. So kann man zwischen folgenden Möglichkeiten wählen:

- Statisch

Die Klassen werden nach der Modi kation wieder gespeichert und können so zu einem beliebigen Zeitpunkt geladen werden. Die Zeit, die für die Veränderung der Klasse gebraucht wird ist nicht relevant, da zum Ladezeitpunkt die modi zierte Klasse ohne irgendwelchen Overhead geladen wird. Deswegen ist dies die beste Methode, wenn auf Performanz Wert gelegt wird. In den späteren Untersuchungen der AOP Ansätze (siehe Kapitel 4) werden hauptsächlich Verfahren genauer betrachtet, welche diese Art der Modi kation unterstützen.

- Zur Ladezeit

Classloader sind verantwortlich, um Klassen vom Dateisystem oder einer anderen Quelle zu laden und der Virtual Machine weiterzureichen. Ein eigener Classloader kann verwendet werden, um in die normale Ladeprozedur einzugreifen und Modi-

kationen durchzuführen, bevor der Bytecode an die VM weitergegeben werden. Dies ist ein eleganter Weg, um die JVM zu erweitern ohne sie zu verändern. Im Abschnitt 3.4.2 wird noch genauer auf dieses Verfahren eingegangen und auch dessen Einschränkungen erläutert.

Im Abschnitt 3.3.1 wurden bereits die verschiedenen Ereignisse vorgestellt, welche die JVM über JVMPI zur Verfügung stellen kann. Hier ist besonders der Event interessant, wenn eine Klasse geladen wird. An dieser Stelle ist es möglich, in den Ladevorgang einzugreifen und diesen zu verändern. Dies führt jedoch dazu, dass bei jedem Ladevorgang eine Überprüfung statt nden muss, ob die aktuelle Klasse verändert werden muss oder nicht. Zu dem in der Zusammenfassung von JVMPI (siehe 3.3.1) erläuterten Overhead kommt also noch der Aufwand für die eigentliche Modi kation dazu. Der Vorteil dieses Verfahren ist wiederrum, dass weiterhin eigene Classloader verwendet werden können. Dieses Verfahren wird oftmals auch bei kommerziellen Pro lern angewandt, da es nicht davon abhängig ist, wie die Anwendung selbst implementiert ist.

- Dynamisch

Dynamic class rede nition ist eine neue Fähigkeit der Java Hotspot[11] VM, welche es Entwicklern und Administratoren erlaubt, eine Klasse innerhalb der JVM zur Laufzeit zu ändern. Diese auch HotSwap genannte Technologie ist ab JDK 1.4 verfügbar und erlaubt in seiner jetzigen Form nur den Austausch von Klassen, bei denen der Code einer Methode verändert wurde. Anspruchsvollere Änderungen werden vielleicht in zukünftigen JDK Versionen unterstützt. Diese Technologie wird z. B. bei AspectWerkz [24] verwendet, um den java.lang.ClassLoader auszutauschen, welche unter 4.2.3 beschrieben wird.

Da es vom Zeitpunkt unabhängig ist, wie die Modi kation gemacht wird, wird zunächst ein Verfahren vorgestellt, mit dem Bytecode verändert werden kann. Anschlieÿend werden die Projekte JMangler und JRat vorgestellt, die weitere interessante Ansätze haben, Codeerweiterungen durchzuführen.

3.4.1 Byte Code Engineering Library (BCEL)

Die Byte Code Engineering Library (BCEL) [25] ist eine Bibliothek, die es ermöglicht, Bytecode schnell und elegant zu verändern. Diese wird hier genauer beschrieben, weil sie bei vielen AOP Ansätzen (z. B. AspectJ, AspectWerkz) verwendet wird.

Weitere Möglichkeiten zur Bytecode Modi kation sind JOIE [26], Jikes Bytecode Toolkit [27] oder das Bytecode Instrumenting Tool (BIT) [28] von Han Bok Lee. Im Gegensatz zu BCEL sind diese immer auf ein spezielles Einsatzgebiet ausgelegt und bieten dem Entwickler nicht den hohen Abstraktionslevel von BCEL.

Zentrales Element von BCEL ist das JavaClass Objekt, welches eine Javaklasse mit all seinen Elementen darstellt. Auf die genaue Struktur einer Klasse wird hier nicht weiter eingegangen, da dies nur zum tieferen Verständnis vom BCEL benötigt wird. Eine gute und kompakte Beschreibung über den Aufbau ist in [29] zu nden. Zwischen den Elementen der JavaClass und den Elementen einer Klasse, wie sie in der JVM spezi ziert wird, existiert eine 1 zu 1 Beziehung. Somit kann eine mit BCEL eingelesene .class Datei wie jedes andere normale Objekt behandelt werden. Die Elemente des Objekts spiegeln die Elemente der Klasse wider und können direkt verändert werden. Wenn dieses Objekt serialisiert wird, kann es, wie jede auf dem normalen Weg kompilierte Quelldatei, in der JVM ausgeführt werden.

BCEL erlaubt es, die Anweisungen auf niedrigster Ebene zu verändern. Sie bietet die Möglichkeit, die Anweisungen mit einem Programm zu untersuchen und zu modi - zieren. Somit kann man Erweiterungen und Verbesserungen während der Laufzeit der Klasse einbauen. Solche Optimierungen können auch durch Verbesserungen des Quelltextes und durch bessere Compiler erreicht werden. Das ist nicht so komplex, da direkt auf dem Sourcecode gearbeitet wird, anstatt mit einzelnen Bytes.

Bytecode Veränderung ist jedoch schneller, da meist der Quelltext nicht zur Ver- fügung steht und Dekompilierung und erneute optimierte Kompilierung viel mehr Zeit benötigt. BCEL vermindert diese Komplexität, indem es die Klasse als Objekt bereit- stellt.

Ein weitere Möglichkeit Bytecode mit Hilfe von BCEL zu verändern, ist load-time re ection . Der Code der Klasse wird beim Laden verändert. Dazu wird ein eigener Classloader verwendet, welcher, anstatt den Bytecode direkt zur JVM weiterzuleiten, diesen mit Hilfe der BCEL API verändert. Nach der Modi kation wird das Ergebnis, wie im normalen Vorgang, an den Byte Code Verier[12] weitergegeben und in der JVM ausgeführt. Abbildung 3.4 zeigt den Ablauf einer solchen Transformation.

Abbildung in dieser Leseprobe nicht enthalten

Abbildung 3.4: Transformation einer Klasse

Die BCEL API kann in einen statischen und einen dynamischen Teil aufgespaltet werden. Der statische Teil wird dafür verwendet, um existierende Klassen zu analysieren, wenn der Quelltext nicht vorhanden ist und wird durch das bereits besprochene JavaClass Objekt repräsentiert.

Die dynamische Hälfte wird dazu verwendet, Klassen zu erzeugen und zu verändern. Dabei wird ein ClassGen Objekt verwendet, welches als Eingabe ein JavaClass Objekt erhält, das die aktuelle Klasse widerspiegelt. Diese Klasse besitzt Funktionen, um nach bestimmten Feldern und Methoden zu suchen, diese zu ersetzen oder zu entfernen. Man kann auch neue Methoden, Felder und Konstanten generieren, indem man Objekte vom Typ MethodsGen, FieldsGen oder ConstentPoolGen erzeugt und dem ClassGen Objekt hinzufügt.

Um das Arbeiten mit BCEL zu erleichtern, sind einige Hilfsklassen vorhanden, wie der BCELi er, der ein JavaClass Objekt in eine BCEL Javaquelldatei umwandelt. Man kann so die Veränderungen, die man gemacht hat, in einem für den Entwickler lesbaren Format darstellen.

Weitere Informationen und Beispiele über BCEL sind in [25] und [29] zu nden.

[...]


[1] Man bezeichnet im Computerbereich traditionell Dateiformate, Protokolle usw. als proprietär, die nicht allgemein anerkannten, herstellerübergreifenden Standards entsprechen, also sozusagen hauseigene Entwicklungen sind.

[1] Java Specification Requests (JSR) sind Spezifizierungsprojekte, die Funktionalitäten festlegen, welche evtl. in zukünftigen Java-Versionen integriert werden.

[2] Unter Aggregation von Daten versteht man das Zusammenfassen detaillierter Daten zu gröÿeren Einheiten.

[3] Von einer nach dem Singleton Pattern implementierten Klasse wird nur eine Instanz erzeugt, welche bis zum Herunterfahren der JVM erhalten bleibt.

[1] Um JMX nutzen zu können, muss bis JDK1.3 die JMX Bibliothek [13] extra mit eingebunden werden.

[2] Ein Java Bean ist ein Java Objekt mit einer standardisierten Konvention (get<Attributname>, set<Attributname>) um auf Objektattribute zugreifen zu können.

[3] Unter Introspection (dt. Selbstbeobachtung) versteht man den Mechanismus, der in der Lage ist die Eigenschaften, Ereignisse und Methoden eines Beans zu ermitteln.

[4] Web Based Enterprise Management (WBEM) ist eine Zusammenfassung von Management und Internet-Technologien. Das Common Information Model (CIM) ist dabei das verwendete Datenmodel.

[5] RMI (Remote Method Invocation) over IIOP (Internet Inter-ORB Protocol) erlaubt auf Objekte auf anderen Rechnern mittels des bei Corba verwendeten Protokolls (ORB) zuzugreifen.

[6] Das Simple Network Management Protocol (SNMP) ist das Internet-Standardprotokoll für Netz-werk Management Software

[7] Das Java Dynamic Management Kit (JDMK) von Sun ist die JMX-Referenzimplementierung mit einer zusätzlichen SNMP Erweiterungsmöglichkeit.

[8] Ein Just-In-Time (JIT) Compiler wandelt den maschinenunabhängigen Java-Bytecode unmittelbar vor dessen Ausführung in Maschinencode des laufenden Systems um. Dadurch wird die Ausführungsgeschwindigkeit um den Faktor 10-20 erhöht.

[9] Weak References können verwendet werden, um Objekte für den Garbage Collektor freizugeben, jedoch kann man weiter darauf zugreifen, wenn diese noch nicht gelöscht wurden.

[10] Management Information Base (MIB) de niert die Variablen, die vom SNMP benötigt werden um Komponenten eines Netzwerks zu überwachen.

[11] Hotspot ist ein dynamischer Compiler, der zur Laufzeit stark frequentierten Code optimiert.

[12] Der Byte Code Veri er ist ein Teil des Interpreters, der korrumpierte Zeilen im Programmtext ndet und Laufzeitregeln überprüft.

Ende der Leseprobe aus 149 Seiten

Details

Titel
Entwurf und Implementierung eines Frameworks für Profiling- und Performancemessungen mit Hilfe von aspektorientierter Programmierung (AOP)
Hochschule
Georg-Simon-Ohm-Hochschule Nürnberg
Veranstaltung
Masterstudiengang
Note
1.0
Autor
Jahr
2004
Seiten
149
Katalognummer
V31579
ISBN (eBook)
9783638325332
ISBN (Buch)
9783638723879
Dateigröße
1330 KB
Sprache
Deutsch
Anmerkungen
Diese Masterarbeit zeigt, dass Aspektorientierte Programmierung (AOP) sehr gut geeignet ist, existierende Anwendungen mit geringem Aufwand zu instrumentieren. AspectJ und AspectWerkz sind z.Z. die beiden AOP-Implementierungen, die für Lasttests sinnvoll verwendet werden können. Für die Ermittlung des besten AOP-Ansatzes wurde ein Lasttestframework entwickelt, welches sehr geringen Overhead besitzt. Bei der Abgabe lag der Arbeit eine CD bei, diese kann hier nicht mitgeliefert werden, Anhang E fehlt daher.
Schlagworte
Entwurf, Implementierung, Frameworks, Profiling-, Performancemessungen, Hilfe, Programmierung, Masterstudiengang
Arbeit zitieren
Michael Dempfle (Autor:in), 2004, Entwurf und Implementierung eines Frameworks für Profiling- und Performancemessungen mit Hilfe von aspektorientierter Programmierung (AOP), München, GRIN Verlag, https://www.grin.com/document/31579

Kommentare

  • Noch keine Kommentare.
Blick ins Buch
Titel: Entwurf und Implementierung eines Frameworks für Profiling- und Performancemessungen mit Hilfe von aspektorientierter Programmierung (AOP)



Ihre Arbeit hochladen

Ihre Hausarbeit / Abschlussarbeit:

- Publikation als eBook und Buch
- Hohes Honorar auf die Verkäufe
- Für Sie komplett kostenlos – mit ISBN
- Es dauert nur 5 Minuten
- Jede Arbeit findet Leser

Kostenlos Autor werden