Ein Eclipse-Plug-in zur statistischen Analyse der

Werbung
FernUniversität in Hagen
Fakultät für Mathematik und Informatik
Lehrgebiet Programmiersysteme
Prof. Dr. Friedrich Steimann
Ein Eclipse-Plug-in zur statistischen
Analyse der Verwendung von Typen in
Java-Programmen
Master-Arbeit im Studiengang
Master of Computer Science
vorgelegt von
Gerd Eichhorn
Marco-Polo-Weg 30
70439 Stuttgart
Matrikelnummer 7117795
[email protected]
Betreuer:
Prof. Dr. F. Steimann
26. Februar 2008
Danksagungen
Mein besonderer Dank gilt Herrn Prof. Dr. Friedrich Steimann für die Übernahme und
Betreuung dieser Arbeit und die zahlreichen weiterführenden Hinweise.
Außerdem geht mein Dank an Herrn Dr. Eugen Grycko vom Fachbereich Mathematik für die großzügige Unterstützung bei der statistischen Analyse und Auswertung.
Danke auch an Frau Dr. Ursula Scheben und Frau Dr. Daniela Keller für die Durchsichten, Korrekturen und Verbesserungsvorschläge dieser Arbeit.
Inhaltsverzeichnis
1 Inhaltsangabe
1
2 Einleitung
2.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Beitrag der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3 Aufbau der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
2
2
3
3 Grundlagen
3.1 Einleitung . . . . . . . . . . . . . . . . .
3.2 Metrik - Number of Declarations (NOD)
3.3 Abstract Syntax Tree . . . . . . . . . . .
3.4 Besucher-Entwurfsmuster . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4 Statistik
4.1 Motivation . . . . . . . . . . . . . . . . . . . . .
4.2 Grundlagen der Bayes-Statistik . . . . . . . . .
4.3 Grundbegriffe der Wahrscheinlichkeitsrechnung:
lungsfunktion und Dichtefunktion . . . . . . . .
4.4 Wahl der Verteilungsfunktion . . . . . . . . . .
4.4.1 Zipf/Estoup-Verteilung . . . . . . . . . .
4.4.2 Yule-Verteilung . . . . . . . . . . . . . .
4.5 Statistisches Analyse-Programm . . . . . . . . .
4.6 Rekursionsalgorithmus . . . . . . . . . . . . . .
4.7 Untersuchung der Beispielprogramme . . . . . .
4.7.1 Beispielprogramme . . . . . . . . . . . .
4.7.2 Untersuchung . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . . .
. . . . . . . . .
Zufallsvariable,
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . .
. . . . .
Vertei. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
4
4
4
7
10
12
12
12
14
16
16
17
18
20
22
22
23
5 Ergebnisse
5.1 Verteilungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Abweichungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3 Fazit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
25
29
29
6 Typ-Analyse-Plug-in (TAP)
6.1 Anforderungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.1.1 Type Diagram View für die grafische Ausgabe der NOD- und NOIMetrik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
31
i
33
Inhaltsverzeichnis
6.1.2
6.2
6.3
6.4
6.5
6.6
6.7
6.8
Type List View für die tabellarische Ausgabe der NOD- und NOIMetrik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.1.3 Detail Diagram View für die grafische Ausgabe der Abhängigkeiten
eines bestimmten Typs . . . . . . . . . . . . . . . . . . . . . . . .
6.1.4 Detail List View für die tabellarische Ausgabe der Abhängigkeiten
eines bestimmten Typs . . . . . . . . . . . . . . . . . . . . . . . .
Praktische Umsetzung . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Material und Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . .
Eclipse-IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
JFreeChart-Bibliothek . . . . . . . . . . . . . . . . . . . . . . . . . . . .
JCommon-Bibliothek . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Launch4j-Applikationswrapper . . . . . . . . . . . . . . . . . . . . . . . .
7 Schlußbetrachtungen
7.1 Zusammenfassung . . . .
7.2 Einsatzmöglichkeiten von
7.3 Ausblick . . . . . . . . .
7.4 Fazit . . . . . . . . . . .
. . . .
TAP .
. . . .
. . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
35
36
37
38
40
40
40
41
41
41
42
42
42
42
43
Abbildungsverzeichnis
44
Tabellenverzeichnis
45
Listingverzeichnis
46
Literaturverzeichnis
47
Inhalt der beiliegenden DVD
48
A Anhang
A.1 Metrik - Number of Instantiations (NOI) . . . . . . . .
A.2 Ermittlung der Typ-Instanziierungen . . . . . . . . . .
A.3 Typ-Analyse-Plug-in (TAP) . . . . . . . . . . . . . . .
A.3.1 Installation des Plug-ins . . . . . . . . . . . . .
A.3.2 Anwendung des Typ-Analyse-Plug-ins . . . . .
A.3.3 File List View für die Ausgabe aller analysierten
A.3.4 Paketstruktur des Plug-ins . . . . . . . . . . . .
A.3.5 Erstellen der JAR-Datei . . . . . . . . . . . . .
A.3.6 Hinzufügen der JFreeChart-Bibliotheken . . . .
A.3.7 Ausgaben des Typ-Analyse-Plug-ins . . . . . . .
A.3.8 Start der Typ-Analyse . . . . . . . . . . . . . .
A.4 Statistisches Auswerteprogramm . . . . . . . . . . . . .
A.4.1 Listing des Programms . . . . . . . . . . . . . .
A.4.2 Erstellen des Eclipse-Projekts . . . . . . . . . .
ii
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
Java-Quellen
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
49
49
50
52
52
52
53
54
55
57
58
59
60
60
70
Inhaltsverzeichnis
A.4.3 Erstellen der JAR-Datei . . . . . . . . . . . . . . . . . . . . . . .
A.4.4 Erstellen der EXE-Datei . . . . . . . . . . . . . . . . . . . . . . .
Erklärung
70
74
78
iii
1 Inhaltsangabe
Die Qualität von Softwareprodukten gewinnt immer mehr an Bedeutung. Doch wie erhält man ein qualitativ hochwertiges Produkt und vor allem, wie kann man die Qualität
messen? Um die Softwarequalität zu quantifizieren, werden in der Softwaretechnik Metriken eingesetzt. Eine spezielle Metrik, die in dieser Arbeit vorgestellt wird, zählt z.B.
für jeden in einem Programm vorkommenden Typ, die Häufigkeit seiner Verwendung.
Diese Quantifizierung kann z.B. dazu benutzt werden, um häufig verwendete Typen zu
optimieren bzw. wenig verwendete Type zu eliminieren. Für den Programmierer ist es
jedoch schwer, bei großen Programmen den Überblick über die verwendeten Typen zu
behalten. Deshalb soll eine Visualisierung der Verteilung der Verwendung entwickelt
werden, um den Programmierer bei der Analyse zu unterstützen.
Im Rahmen dieser Arbeit wurde dazu ein Typ-Analyse-Plug-in (TAP) entwickelt. Es
stellt die Verwendung der verschiedenen Typen in Java-Programmen dar. Die Ausgabe erfolgt in Tabellen und Histogrammen. Außerdem kann man mit dem TAP-Plug-in
zählen, wie oft innerhalb eines Java-Programms Instanzen von einem bestimmten Typ
erzeugt werden.
Ein weiterer Teil der Arbeit beschäftigt sich mit der statistischen Analyse der zuvor gewonnenen Ergebnisse. Es soll geklärt werden, ob sich die Verteilung der in JavaProgrammen benutzten Typen an die, aus der Statistik bereits bekannten, Verteilungsfunktionen anlehnt. Hierzu wird auf die Methoden der sogenannten Bayesschen Stati”
stik“ zurückgegriffen.
Als Entwicklungsplattform wurde Eclipse, eine Open-Source-Entwicklungsumgebung,
ausgewählt, die vor allem einen guten Erweiterungsmechanismus basierend auf Plugins bietet. Das statistische Analyseprogramm wurde ebenfalls mit Hilfe von Eclipse als
Erweiterung des JDT’s als eigenständige Java-Applikation realisiert.
1
2 Einleitung
2.1 Motivation
Bei der Programmierung kann es am Ende des Entwicklungszyklus hilfreich sein, sich
einen Überblick über die verwendeten Typen zu verschaffen. Dies kann aus zwei Gründen
sinnvoll sein. Es können Typen identifiziert werden, die sehr häufig bzw. sehr selten im
Programm vorkommen. Daraus kann man Optimierungen für das Programm ableiten,
indem man häufig verwendete Typen optimiert, z.B. die Methoden einer Klasse bezüglich
Laufzeit verbessert. Andererseits können auch z.B. einfache, selten benutzte, selbstgeschriebene Typen durch Typen aus Bibliotheken ersetzt werden, wenn diese die benötigte
Funktionalität bereitstellen. Als Beispiel sei hier die aus der Programmiersprache C++
bekannte Standard Template Library“ (STL) genannt, die z.B. fertige Klassen für Li”
sten, Vektoren, Stacks usw. enthält. Alternativ sei hier die für die Programmiersprache
Java bekannte Chart-Bibliothek JFreeChart“ genannt, mit deren Hilfe man vorhandene
”
Messdaten recht einfach zur grafischen Ausgabe, z.B. in Kuchencharts aufbereiten kann.
Durch den extensiven Einsatz sind diese Bibliotheken meist frei von Fehlern und zudem
auf die Laufzeit hin optimiert. Diese Standardtypen“ können so Fehler vermeiden und
”
auch die Lesbarkeit von Programmen verbessern.
2.2 Beitrag der Arbeit
Die vorliegende Arbeit hat zum einen das Ziel, bestehende Java-Programme auf die
verwendeten Typen hin zu untersuchen. Zu diesem Zweck wird eine spezielle Metrik eingeführt, die für jeden in einem Java-Programm vorkommenden Typ die Häufigkeit seiner
Verwendung mißt. Zum anderen soll mit einer allgemeinen statistischen Auswertung der
vorangegangenen Analyse-Ergebnisse eine Aussage über die Verteilung der Typen gemacht werden. Hierzu sollen die Ergebnisse aus den vorangegangenen Untersuchungen
von Java-Projekten weiterverwendet werden.
Die hierbei gewonnenen Daten können auch als Eingabe für weitere Programme/Plugins dienen. So könnten z.B. automatisierte Refactorings auf Java-Quellen durchgeführt
werden, die als Eingabe die Daten der Typ-Analyse benötigen.
Aufbauend auf diesen beiden Anforderungen wurde für den ersten Teil ein Plug-in
entwickelt, welches bestehende Java-Programme untersucht. Die Ergebnisse werden sowohl tabellarisch als auch grafisch dargestellt. Als Nebenprodukt wird zusätzlich gezählt,
wie oft innerhalb eines Java-Programms Instanzen von einem bestimmten Typ erzeugt
werden. Dieser Schritt wurde für zukünftige Arbeiten mit implementiert, da es nur einen
geringen Zusatzaufwand bedeutet.
2
KAPITEL 2. EINLEITUNG
Für den zweiten, statistischen Teil wurde ein Java-Programm entwickelt, welches eine
Aussage über die, aus der Literatur bekannten Verteilungen erlaubt. Hierzu wird auf die
sog. Bayessche Statistik“ zurückgegriffen, die eine hinreichend genaue Interpretation der
”
Ergebnisse erlaubt.
2.3 Aufbau der Arbeit
Das Kapitel 3 beschreibt die Metrik, mit der die Häufigkeit der Verwendung von Typen
gemessen wird und die im weiteren in dem Typ-Analyse-Plug-in umgesetzt wird. Das
Typ-Analyse-Plug-in wird in Kapitel 6 behandelt. Anschließend erfolgt die Beschreibung des statistischen Teils der Arbeit in Kapitel 4. Die Untersuchung der einzelnen
Beispielprogramme und deren Ergebnisse fließen dann in das Kapitel 5 ein. Dort wird
außerdem die Eingruppierung der Typ-Analyse-Ergebnisse der untersuchten Programme dargestellt. Die Ergebnisse, in Form von Häufigkeitszählungen von Typen in JavaProgrammen, bilden jeweils eine bestimmte Typ-Verteilung. Diese Typ-Verteilungen werden mit den aus der Mathematik bekannten Verteilungen verglichen bzw. bewertet. Die
beiden Kapitel Diskussion“ und Schlußbetrachtungen“ schließen die Arbeit ab.
”
”
3
3 Grundlagen
3.1 Einleitung
Das vorliegende Typ-Analyse-Plug-in sucht in einer Menge von Java-Quellen nach den
in ihnen deklarierten Typen sowie nach anderen Deklarationselementen, in denen Typen verwendet werden. Um deklarierte Typen zu finden, werden die Java-Quellen nach
Schnittstellen- und Klassendeklarationen durchsucht sowie nach Deklarationen von Aufzählungstypen. Ein Typ wird als verwendet betrachtet, wenn er in Parameterdeklarationen von Konstruktoren oder Methoden, als Rückgabetyp von Methoden oder in Variablendeklarationen vorkommt. Unter dem Begriff Variablendeklaration werden Attributdeklarationen und lokal in Methoden vorkommende Variablendeklarationen zusammengefasst. Neben der Suche nach Deklarationselementen, in denen ein Typ A verwendet
wird, wird auch nach Programmstellen gesucht, in denen Instanzen von A erzeugt werden. Vom Analyse-Plug-in werden zwei Metriken implementiert, eine, die für einen Typ
A die Anzahl seiner Verwendungen angibt und eine weitere, die die Anzahl der Instanziierungen von A mißt. Die erste Metik wird im Folgenden vorgestellt, die zweite im
Anhang A.1.
3.2 Metrik - Number of Declarations (NOD)
Die Metrik, die die Verwendung eines Typs zählt, basiert auf einer statischen TypAnalyse von Java-Programmen und kann folgendermaßen angegeben werden:
N OD(A) = | { d | d ∈ D ∧ A ∈ d } |
wobei A ein Typ ist und D die Menge aller betrachteten Deklarationselemente.
Zu D gehören in Konstruktoren und Methodenden vorkommende Parameterdeklarationen, Deklarationen des Rückgabetyps von Methoden sowie Variablendeklarationen wie
in Kapitel 3.1 eingeführt.
• Falls d eine Parameter- oder Variablendeklaration repräsentiert, bedeutet A ∈ d,
daß A in d als der statische Typ des Parameters bzw. der Variablen festgelegt wird.
• Falls d die Deklaration des Rückgabetyps einer Methode repräsentiert, bedeutet
A ∈ d, daß A als Rückgabetyp angegeben ist.
4
KAPITEL 3. GRUNDLAGEN
Der folgende Algorithmus in Form von Pseudocode beschreibt, wie die Anzahl der Verwendungen innerhalb des Analyse-Plug-ins bestimmt wird:
1
2
3
4
f or each declarationElement of actualProject do {
Type := getTypeOfDeclarationElement ;
CountingArray [ Type ]++;
}
Listing 3.1: Algorithmus zur Berechnung der Metrik NOD
Unter die bei der Analyse erfassten Typen fallen nicht nur die im untersuchten Quelltext deklarierten Schnittstellen-, Klassen- und Aufzählungstypen, sondern sämtliche, im
Quelltext i.o. Sinne verwendeten Typen, also auch Basisdatentypen wie z.B. int und
float etc. oder vordefinierte Typen wie java.lang.String etc. Die im untersuchten Quelltext deklarierten Typen besitzen nur insofern eine Sonderstellung, als daß Sie später
bei der Auswertung der Analyseergebnisse auch dann aufgeführt werden, wenn sie im
untersuchten Quelltext an keiner Stelle verwendet werden. Ihre Verwendung wird dann
mit 0 angegeben. Der Sinn dieser Sonderstellung wird weiter unten erläutert.
Die folgende Aufzählung gibt noch einmal alle Typen an, die in die Analyse eingehen:
• Rückgabetypen von Methoden
• Typen von Methoden- und Konstruktorparametern
• Typen von lokal in Methoden deklarierten Variablen
• Typen in Attributdeklarationen
• Klassentypen, die im untersuchten Quelltext deklariert werden
• Schnittstellentypen, die im untersuchten Quelltext deklariert werden
• Aufzählungstypen, die im untersuchten Quelltext deklariert werden.
Um diese Typen zu bestimmen, müssen bei der Analyse also folgende Javakonstrukte
untersucht werden:
• Konstruktordeklarationen
• Methodendeklarationen
• Deklarationen von Variablen innerhalb von Methodenrümpfen
• Attributdeklarationen
• Klassendeklarationen
• Schnittstellendeklarationen
5
KAPITEL 3. GRUNDLAGEN
• Deklarationen von Aufzählungstypen
Das folgende Beispiel dient zur Verdeutlichung des Verfahrens:
1
2
3
public c l a s s SquareRoot {
private double squareRoot ;
public double getSquareRoot ( ) { return squareRoot ; }
4
public void calcSquareRoot ( double d ) {
String s ;
squareRoot = Math . sqrt ( d ) ;
s = "Die Quadratwurzel von <" + d + "> ist: " + squareRoot ;
System . out . println ( s . toString ( ) ) ;
}
5
6
7
8
9
10
11
}
Listing 3.2: Beispielcode mit relevanten Deklarationselementen
Das Beispiel hat das folgende Ergebnis:
Typ
Anzahl der Verwendungen des Typs
void
1
double
3
java.lang.String
1
SquareRoot
0
Tabelle 3.1: Auswertung des Beispielcodes
Eine Besonderheit ist hier anzumerken: Der letzte Typ der Tabelle, in Form der Klasse
SquareRoot“, wird hier aufgelistet, hat aber eine Anzahl von null Verwendungen, da
”
der Typ zwar deklariert, nicht aber in anderen Deklarationselementen verwendet wird.
Dies könnte bei einer späteren Untersuchung eines Programms ein Hinweis auf eine nicht
benötigte Klasse sein.
6
KAPITEL 3. GRUNDLAGEN
3.3 Abstract Syntax Tree
Für die Untersuchung von Java-Quelldateien wird von Eclipse der sogenannte AST bereitgestellt. Der AST ist mit dem Document Object Model“ (DOM) einer XML-Datei
”
vergleichbar. Ähnlich dem DOM erlaubt der AST den Baum zu modifizieren. Die Änderungen in einem AST stellen dann anschließend die Modifikationen im Quellcode dar.
Der AST stellt dem Programmierer also Informationen über eine Java-Quelle zur Verfügung. Beim Aufbau eines ASTs wird ein Quelltext in seine logischen Bestandteile zerlegt. Das bedeutet, daß jeder Knoten im AST ein bestimmtes Element der Sprache Java
repräsentiert. Dies können z.B. Methodendeklarationen, Typdeklarationen, Variablendeklarationen usw. sein. Ein Anwenderprogramm kann nun diesen Syntaxbaum rekursiv
durchlaufen, um die Informationen, an denen es interessiert ist, zu erhalten. So kann
z.B. bei der Untersuchung einer Methodendeklaration der Rückgabetyp und der bzw.
die Typ(en) der Methodenparameter festgestellt werden. Der AST erlaubt außerdem die
Modifikation von Quellcode. Dies geschieht durch das Zurückschreiben des modifizierten ASTs. Im Quellcode ist dieses Feature beispielsweise für automatische Refactorings
und das Eclipse-Werkzeug Quick Fix“ von großem Nutzen. Für eine praktische Ein”
führung bietet sich der Artikel AST [5] aus dem Artikelbereich der Eclipse-Community
www.eclipse.org/articles an. Die Abbildung 3.1 zeigt den Workflow“ des ASTs.
”
Abbildung 3.1: AST-Workflow
• 1. Zu parsende Java-Quelle
• 2. Aufruf des Parsers mit Hilfe der Klasse org.eclipse.jdt.core.dom.ASTParser“
”
• 3. Der Abstract Syntax Tree“ als Resultat von Schritt 2
”
7
KAPITEL 3. GRUNDLAGEN
• 4a. Manipulation des ASTs entweder direkt, z.B. Ändern von Knoteneigenschaften
• 4b. Modifikationen in einem separaten sogenannten Protokoll“, d.h. mit dem Auf”
ruf von ASTRewrite“ wird eine Kopie des ASTs erzeugt, wo anschließend die
”
Modifikationen durchgeführt werden
• 5. Zurückschreiben der Änderungen
• 6. IDocument, ist ein sogenannter Wrapper“ für den Quellcode und wird bei Punkt
”
1. und 5. verwendet
Als weiteres Hilfsmittel wird ein sogenannter AST-View“ von der Eclipse-Community
”
zur Verfügung gestellt. Mit dessen Hilfe kann eine Java-Quelle geladen und anschließend
direkt untersucht werden. Als Ergebnis wird der resultierende AST grafisch dargestellt
und kann auf bestimmte Typen/Konstrukte hin durchsucht werden. Dies ist auch eine
gute Möglichkeit seine eigenen Programme, die den AST von Java-Quellen benutzen
oder modifizieren, auf Korrektheit hin zu überprüfen. Der oben stehende Beispielcode
aus Listing 3.2 führt zu dem AST in Abbildung 3.2.
Einige beispielhaft aufgeklappte Knoten zeigen die zugehörigen Details. Z.B. zeigt
die TypeDeclaration“ den Name des Typs in der untersuchten Quelle, in diesem Fall
”
der Name der Klasse SquareRoot“ im Knoten SimpleName“. Ein sogenannter Sim”
”
”
pleName“ ist irgendein String einer Java-Quelle, die kein Schlüsselwort, ein Boolesches
Literal (true oder false) oder das null“-Literal ist. In den weiteren Knoten innerhalb
”
des Rumpfes BODY DECLARATIONS“ folgen die FieldDeclaration“ der Memberva”
”
riable squareRoot“. Anschließend folgt die Funktion getSquareRoot“ innerhalb einer
”
”
MethodDeclaration“. Hier ist der Modifier“ in Form von public“ zu erkennen, der
”
”
”
Rückgabetyp double“ in einem Knotentyp namens PrimitiveType“. Primitive Typen
”
”
sind alle Basistypen, die die Sprache Java zur Verfügung stellt, z.B. int, long, double,
usw.
8
KAPITEL 3. GRUNDLAGEN
Abbildung 3.2: AST-View
9
KAPITEL 3. GRUNDLAGEN
3.4 Besucher-Entwurfsmuster
Um Informationen von einer Java-Quelle, wie z.B. den Rückgabetyp einer Methode, zu
erhalten, muß der sogenannte Abstract Syntax Tree“ (AST), siehe hierzu Kapitel 3.3, der
”
Java-Quelle analysiert werden. Dazu muß zunächst der AST erzeugt werden, um anschließend durchlaufen zu werden. Das aus der Literatur bekannte Besucher-Entwurfsmuster
(engl.: Visitor-Designpattern) ist im Zusammenhang mit dem Durchlaufen eines ASTs
von Bedeutung. Einen guten Einstieg bietet der englischsprachige Artikel von Wikipedia
unter der URL http://en.wikipedia.org/wiki/Visitor_pattern an oder das Standardwerk Design Pattern“ von E. Gamma et al. [15]. Sollen die vom Eclipse-Framework
”
angebotenen Funktionen für die Untersuchung eines ASTs verwendet werden, so müssen
für das Durchlaufen eines ASTs vom Anwender sogenannte Besucherfunktionen, unter
Verwendung der Besucherklasse ASTVisitor“ realisiert werden. Es müssen dann die
”
Funktionen zum Auffinden von Informationen überschrieben werden, an denen der Anwender interessiert ist. Das folgende Beispiel zeigt den grundsätzlichen Aufbau für das
Aufsammeln von Daten, an denen ein Anwenderprogramm interessiert ist.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public c l a s s TypeDeclarationVisitor extends ASTVisitor {
...
public boolean visit ( VariableDeclarationFragment node ) {
...
}
// Ueberschreiben der Besucherfunktion mit dem Parameter
// " MethodDeclaration ", um an Infos zu diesem Typ zu gelangen
public boolean visit ( MethodDeclaration node ) {
// Resolve binding
IMethodBinding methodBinding = node . resolveBinding ( ) ;
// Retrieve parameter types
ITypeBinding [ ] paramTypes = methodBinding . getParameterTypes ( ) ;
...
// Retrieve return type
ITypeBinding returnType = methodBinding . getReturnType ( ) ;
...
return super . visit ( node ) ;
}
public boolean visit ( EnhancedForStatement node ) {
...
}
public boolean visit ( TypeDeclaration node ) {
...
}
}
Listing 3.3: Beispiel für Besucherfunktionen zum Auswerten von AST-Daten
10
KAPITEL 3. GRUNDLAGEN
Der vorhergehende Beipielcode ist auch Teil des Typ-Analyse-Plug-ins. Dort werden
die von den überschriebenen Funktionen gelieferten Daten ermittelt und anschließend in
Tabellen aufgesammelt. So liefert z.B. die Besuchermethode mit dem Knotentyp Me”
thodDeclaration“ als Parameter sowohl den Typ des Rückgabewertes als auch sämtliche
Typen der übergebenen Aufrufparameter, wie im Beispiel funktional grob angedeutet
wird.
11
4 Statistik
In diesem Kapitel wird die Untersuchung der mit dem Typ-Analyse-Plug-in gewonnenen Daten mit Hilfe der Bayesschen Statistik gemacht. Es werden zwei Verteilungen
angegeben und untersucht, ob die gewonnenen Daten diesen Verteilungen gehorchen.
4.1 Motivation
Wie eingangs bereits erwähnt, bildet die Bayes-Statistik“ die Grundlage für die nun
”
folgende statistische Untersuchung von Typhäufigkeiten in Java-Programmen. Für eine
Einführung sei hier [7], Fahrmeir [14] Kapitel 4.7, Koch [8] und Moeschlin/Steinert [13]
empfohlen. Auf Koch geht auch der gleich folgende Abschnitt über die Bayes-Statistik
zurück.
Mit Hilfe der Bayes-Statistik können willkürlich erhobene Daten, z.B. aus Häufigkeitszählungen von Typen in Java-Programmen, statistisch untersucht werden. Insbesondere
ist mit der Bayesschen Methodik das Konzept der sogenannten A-Priori“-Informationen
”
verbunden. Das heißt, daß in die statistische Datenanalyse Informationen mit einbezogen werden, die bereits vor der Erhebung der Daten vorliegen. Das Ziel der Bayesschen Methodik ist die Kombination der beiden Informationsquellen, d.h. der A-PrioriInformationen, in Form von Erfahrungen oder Expertenwissen, und der Daten selbst.
Im Mittelpunkt der Bayes-Statistik steht das sogenannte Bayes-Theorem“, mit dem
”
sich unbekannte Parameter der zugrunde liegenden und vermuteten Verteilungsfunktion schätzen lassen. Als Ergebnis einer solchen Analyse ergibt sich die sogenannte A”
Posteriori-Verteilung“. Wie der Name bereits sagt, enthält die A-Posteriori-Verteilung
die durch die Beobachtung von Stichproben der zu analysierenden Daten gewonnene
Information über den oder die unbekannten Parameter. Dadurch kann eine qualitative
Aussage über die Wahrscheinlichkeit gemacht werden, ob die analysierten Daten einer
bestimmten Verteilungsfunktion gehorchen oder auch nicht.
4.2 Grundlagen der Bayes-Statistik
In der Bayes-Statistik wird die Wahrscheinlichkeit von Aussagen definiert, wobei die
Wahrscheinlichkeit ein Maß für die Plausibilität der Aussage liefert. Die Bayes-Statistik
beruht auf dem sogenannten Bayes-Theorem“. Mit seiner Hilfe lassen sich unbekannte
”
Parameter schätzen, Konfidenzregionen für die unbekannten Parameter festlegen und
die Prüfung von Hypothesen für diese Parameter ableiten. Eine Aussage hängt im allgemeinen davon ab, ob eine weitere Aussage wahr ist. Deshalb arbeitet die Bayes-Statistik
ausschließlich mit bedingten Wahrscheinlichkeiten:
12
KAPITEL 4. STATISTIK
In der Wahrscheinlichkeitsrechnung ist P(A|B) die Wahrscheinlichkeit für ein Ereignis
A unter der Bedingung, daß B eintritt. In der Bayes-Statistik gibt diese bedingte Wahrscheinlichkeit ein Maß für die Plausibilität der Aussage A|B an, d.h. daß die Aussage
A richtig ist, wenn B gilt. Das Bayes-Theorem der Wahrscheinlichkeitsrechnung hat die
folgende Gestalt:
Sei Ω die Menge aller möglichen Ergebnisse (Ergebnisraum), E eine Familie von Teilmengen von Ω, die eine ρ -Algrbra bildet (Ereignisalgebra) und P : E → R+ ein Wahrscheinlichkeitsmaß. Sei A ∈ E mit P(A) > 0 und {B , ..., Bn |Bj ∈ E} eine disjunkte Zerlegung
von Ω mit P (Bi ) > 0 für i = 1, ..., n. Dann gilt:
P (A|Bk ) · P (Bk )
P (Bk |A) = P
n
P (A|Ei ) · P (Ei )
(4.1)
i=1
Eine typische Anwendung wie zum Beispiel in der Medizin ergibt sich, wenn man die
Wahrscheinlichkeit P(Ursache|Symptom) bestimmen will, aber viel leichter etwas über
P(Symptom|Ursache) herausfinden kann.
Praktisches Beispiel:
Das nun folgende Beispiel wurde aus Hartung [7] entnommen. Durch einen zu spät
erkannten Fabrikationsfehler sind in einer Automobilproduktion genau 20 defekte Lenkgetriebe eingebaut worden. In einer Rückrufaktion wurden 200000 Wagen dieser Serie
überprüft und alle als fehlerhaft identifizierten Lenkgetriebe wurden ausgetauscht. Dabei
wird die Überprüfung mit 99%-iger Sicherheit zu einem korrekten Ergebnis führen. Wie
groß ist die Wahrscheinlichkeit, daß ein ausgewechseltes Lenkgetriebe auch defekt war?
Es werden die folgenden Bezeichnungen verwendet:
B1 sei das Ereignis eines defekten Lenkgetriebes.
B2 sei das Ereignis eines nicht defekten Lenkgetriebes.
A sei das Ereignis eines ausgewechselten Lenkgetriebes.
Die folgenden Informationen sind gegeben:
20
P (B1 ) =
= 0.0001 P (A|B1 ) = 0.99 P (A|B2 ) = 0.01
200000
Gesucht ist die Wahrscheinlichkeit
P (Bk |A) = P (Lenkgetriebe def ekt|Lenkgetriebe ausgewechselt)
Mit dem Theorem von Bayes folgt nun:
P (B1 |A) =
P (A|B1 ) · P (B1 )
2
P
P (A|Ei ) · P (Ei )
i=1
=
0.99 · 0.0001
≈ 0.0098
0.99 · 0.0001 + 0.01 · 0.9999
13
KAPITEL 4. STATISTIK
Fast alle ausgewechselten Lenkgetriebe waren demnach nicht defekt.
In der Bayes-Statistik wird diese Formel noch durch eine Aussage über zusätzliches Wissen ergänzt. Der Einfachheit halber schreiben wir diese Formel nur für die Ergebnisse
A,B und C auf:
P (A|BC) =
P (A|C) · P (B|AC)
P (B|C)
(4.2)
Dabei bedeutet:
A die Aussage über ein unbekanntes Phänomen
B die Aussage, die Information über das unbekannte Phänomen enthält
C eine Aussage über zusätzliches Wissen
Man bezeichnet:
P(A|C) als Priori-Wahrscheinlichkeit
P(A|BC) als Posteriori-Wahrscheinlichkeit und
P(B|AC) als Likelihood
Beispiel:
Laplace schätzte die Masse des Saturns anhand vorhandener astronomischer Beobachtungen seiner Umlaufbahn. Diese Daten aus dem 18.Jahrhundert ließen eine Schätzung
der Masse und eine Vorhersage auf ein Prozent Genauigkeit zu. Dieser Wert wurde bis
heute nur um 0.63 Prozent korrigiert.
In Formel 4.2 ist dabei:
A: Die Masse des Saturn MS liegt in einem bestimmten Intervall
B: Daten von Observatorien über gegenseitige Störungen von Jupiter und Saturn
C: common sense“, daß die Masse des Saturn weder so klein sein kann, daß er seine
”
Ringe verliert, noch so groß, daß er das Sonnensystem zerstört
4.3 Grundbegriffe der Wahrscheinlichkeitsrechnung:
Zufallsvariable, Verteilungsfunktion und
Dichtefunktion
In vielen Fällen benötigt man quantitative Aussagen über das Auftreten bestimmter
Zahlenwerte als Ergebnis eines Zufallsversuchs. Das Ereignis“ besteht in diesem Fall
”
darin, daß eine zufällige“ Größe X einen vorher fixierten Wert annimmt oder (etwas
”
allgemeiner formuliert) einen Wert in einem festgelegten Intervall liefert. Dies führt auf
den Begriff der Zufallsvariablen:
14
KAPITEL 4. STATISTIK
Eine Funktion X : Ω → R heißt Zufallsvariable, wenn für jedes c ∈ R die Menge
Ec := {ω ∈ Ω | X(ω) ≤ c}
(4.3)
ein Ereignis in dem betrachteten Wahrscheinlichkeitsraum ist.
Um beschreiben zu können, welche Werte eine Zufallsvariable X mit einer bestimmten Wahrscheinlichkeit annimmt, macht man folgende Begriffsbildung:
Sei X eine Zufallsvariable. Dann heißt die durch
FX (x) = P ({ω ∈ Ω | X(ω) ≤ x}), x ∈ R
(4.4)
gegebene Funktion FX die Verteilungsfunktion der Zufallsvariablen X.
Für b > a gilt:
FX (b) − FX (a) = P (a < X ≤ b)
(4.5)
Eine Zufallsvariable heißt kontinuierlich (oder stetig), falls eine Darstellung der Form
Zx
FX (x) =
f (t) dt
(4.6)
−∞
mit einer nichtnegativen integrierbaren Funktion f möglich ist. f nennt man die Dichtefunktion (oder Dichte) der Zufallsvariablen X.
Wenn eine Zufallsvariable X eine Dichtefunktion fX besitzt, dann gilt für a < b:
Zb
P (a < X ≤ b) =
fX (t) dt.
(4.7)
a
Verteilungsfunktion und Dichtefunktion enthalten die gleichen Informationen über eine
kontinuierliche Zufallsvariable. Das Bild einer Dichtefunktion ist aber sehr viel aussagekräftiger. Man beachte aber, daß die Dichtefunktion selbst keine direkte Interpretation
als Wahrscheinlichkeit erlaubt, erst die Integration führt zu Wahrscheinlichkeiten.
15
KAPITEL 4. STATISTIK
4.4 Wahl der Verteilungsfunktion
Die Frage nach den Worthäufigkeiten in beliebigen Texten beschäftigte viele Mathematiker. So fand J.B. Estoup 1916 ein Gesetz über die Häufigkeit der Benutzung von Wörtern,
das 1935 von G.K. Zipf formuliert und von G.U. Yule und B. Mandelbrot und anderen
weiterentwickelt wurde. Siehe hierzu auch Artikel Bibliometrie“ [4] im WWW bei Wiki”
pedia - Die freie Enzyklopädie. Die Zipf/Estoup-Verteilung und die Yule-Verteilung sind
im Zusammenhang mit Worthäufigkeiten, siehe auch Johnson [6], aus dem Bereich der
Linguistik bekannt. Dort erklären sie die Anzahl des Auftretens von Wörtern in einem
beliebigen Text. Von daher liegt es nahe, diese beiden Verteilungen auszuwählen, um
zu testen, ob die gemessenen Daten (Typhäufigkeiten in Java-Programmen) einer dieser
beiden Verteilungen gehorchen. Sei P[x=r] die Wahrscheinlichkeit, daß ein Wort x in
einem Text r-mal auftritt.
4.4.1 Zipf/Estoup-Verteilung
Die Zipf/Estoup-Verteilung, in der Literatur teilweise auch Zeta“-Verteilung genannt,
”
ergibt sich aus der Näherungsformel, wie sie in Johnson [6] beschrieben ist:
nr ∝ r−(ρ+1) (r = 1, 2, ...; ρ > 0)
(4.8)
wobei nr die Anzahl der Worte ist, die r mal auftreten:
P [x = r] = cr−(ρ+1) (r = 1, 2, ...)
(4.9)
mit
c := [ζ(ρ + 1)]−1
(4.10)
wobei ζ(...) die Zeta-Funktion
ζ(x) =
∞
X
1
1
1
1
=
1
+
+
+
+ ···
x
x
x
x
n
2
3
4
n=1
beschreibt. Diese Verteilungsfunktion wird auch Zeta-Verteilung genannt.
16
(4.11)
KAPITEL 4. STATISTIK
4.4.2 Yule-Verteilung
Die Yule-Verteilung ist ebenfalls in Johnson [6] beschrieben und lautet wie folgt:
P [x = r] = Aρ B(r, ρ + 1) (r = 1, 2, ...)
(4.12)
mit
"
Aρ =
∞
X
#−1
B(r, ρ + 1)
(4.13)
Γ(α) · Γ(β)
Γ(α + β)
(4.14)
r=1
und
B(α, β) =
als Beta-Funktion, wobei die Gammafunktion durch
Γ(t) =
t · eγt ·
∞ Y
k=1
t
1+
k
!−1
− kt
·e
mit γ = 0.577216...
(4.15)
gegeben ist.
Der unbekannte Parameter ρ stellt hier im konkreten Fall den zu bestimmenden Parameter in der zugrunde liegenden Verteilungsfunktion dar. Dies ist der Wert auf der
x-Achse, wo der zugehörige y-Wert sein Maximum erreicht. Dieser Wert stellt dann für
die untersuchten Daten das optimale Ergebnis dar. Sprich, mit diesem Wert des optimalen Parameters ρ können die Daten am besten erklärt werden.
17
KAPITEL 4. STATISTIK
4.5 Statistisches Analyse-Programm
Grundlage des Analyseprogramms ist das Bayes-Theorem. Es wird damit eine Wahrscheinlichkeitsschätzung durchgeführt, um eine Aussage über die beiden vorab vermuteten Verteilungen zuzulassen. Dazu wird der in Abschnitt 4.6 beschriebene Rekursionsalgorithmus benötigt.
Als Eingabe dienen jeweils die von den Java-Testprogrammen ermittelten Typ-Verteilungsdaten in Form der TXT-Datei, die mit dem Typ-Analyse-Plug-in erzeugt werden.
Diese Datei wird beim Start eingelesen und anschließend weiterverarbeitet bzw. interpretiert. Für die A-Priori-Daten wird eine Gleichverteilung angenommen, da vorab keine
Ausage über die Verteilung der Eingabedaten vorliegt. Das Ergebnis stellt sich in Form
einer Wahrscheinlichkeitsdichtefunktion dar, die angibt, wie wahrscheinlich die Messdaten sich einer empirisch ermittelten Yule- bzw. Zipf/Estoup-Verteilung annähern. Ist
eine solche Dichtefunktion vorhanden, so stellt das Maximum der Funktion das optimale Ergebnis (die größte Wahrscheinlichkeit) bezogen auf die zu analysierenden Daten
dar. In Abbildung 4.1 ist beispielhaft die (Wahrscheinlichkeits-)Dichtefunktion für die
Yule-Verteilung dargestellt. Die Grundlage für dieses Beispiel sind die Ergebnisse der
Typ-Analyse des Programms ”JUnit 3.8.2”.
Abbildung 4.1: Statistisches Analyse-Programm
Je ausgeprägter, d.h. je höher und schmaler dieser Peak ist, desto besser passen die
getroffenen Annahmen über die Verteilungen auf die zu analysierenden Daten. In diesem
Fall gibt es genau einen Parameterwert ρ mit maximalem Gewicht. Im Sinne der BayesStatistik wird dieser Parameterwert als optimaler Parameter“ zur Beschreibung der
”
Stichprobe herangezogen. Damit hat man einen guten Hinweis, daß die vorab getroffenen
18
KAPITEL 4. STATISTIK
Annahmen korrekt sind. Ergibt sich kein solcher Peak, so kann man daraus schließen,
daß die zuvor getroffenen Annahmen nicht zutreffend sind und die Daten keiner der
beiden Verteilungen entsprechen.
Im obigen Beispiel ergibt sich nur“ für die Yule-Verteilung ein Peak. Bei kleinen Pro”
grammen kann es vorkommen, daß sich für beide Verteilungen ein Peak ergibt. Dies kann
damit erklärt werden, daß sich die beiden Verteilungen recht ähnlich sind und es erst
bei einer größeren Datenmenge zu einem eindeutigen Ergebnis kommt. Der ausgeprägtere der beiden Peaks stellt dann einen statistischen Hinweis dar, daß die zugehörige
Verteilung die Daten besser erklärt als die andere Verteilung.
Dieses Merkmal ist auch bei den anderen untersuchten Programmen der Fall, wie
später bei den Ergebnissen zu sehen sein wird. Es ergibt sich immer eine eindeutige Zuordnung zu einer der beiden Verteilungen. Falls sich kein solcher Peak einstellen würde,
so muß man annehmen, daß die vorliegenden Daten auf keine der beiden Verteilungen
passen. Die Folge daraus wäre dann, daß die Daten einer anderer Verteilung gehorchen,
die die Daten besser erklärt. Es könnte aber auch sein, daß es sich um eine neue, unbekannte Verteilungsfunktion handelt.
Auf der rechten Seite ist das Diagramm der Verteilungen zu sehen. Hierbei wird die
Verteilung der Typ-Analysedaten in Form der blauen Kurve aufgetragen. Zum Vergleich
werden zusätzlich die beiden bekannten Verteilungen Yule (rote Kurve) und Zipf/Estoup (magenta Kurve) in Form einer optimalen Verteilung zum Vergleich dargestellt.
Man kann an diesem Bespiel gut erkennen, wie gut sich die Typ-Analysedaten an die
beiden bekannten Verteilungen annähern. Den Ausschlag zu einer der beiden bekannten
Verteilungen gibt dann letztlich die Abweichung. Diese Abweichung wird berechnet und
unterhalb der Diagrammbeschriftung ausgegeben. Der kleinere Wert sagt dabei aus, zu
welcher der beiden bekannten Verteilungen die Daten besser passen. Dies wird außerdem
durch die Dichtefunktion auf der linken Seite des Diagramms bestätigt.
Das komplette Listing des statistischen Analyseprogramms befindet sich im Anhang
A.4.1.
19
KAPITEL 4. STATISTIK
4.6 Rekursionsalgorithmus
Hier folgt der in Moeschlin et al. [13] dargestellte Rekursionsalgorithmus. Grundlage für
das Folgende ist die Kollektion
W := {P (γ; .) | γ ∈ G}
(4.16)
möglicher Stichprobenverteilungen, wobei im diskreten Fall P [., .] durch eine (r × m)Matrix p[., .] gegeben ist. Nach der Grundannahme eines statistischen Experiments existiert in der vorgegebenen Kollektion W der möglichen Stichprobenverteilungen genau
eine Verteilung p[w, .], die wahr ist, d.h. die Stichprobenwerte sind unabhängige Replikanten eben dieser Verteilung.
Für die Zug um Zug anfallende Stichprobenrealisation setzt man aus Gründen zweckmäßiger Schreibweise das Symbol k“ anstelle von x“. Zunächst wird ein gemäß p[w, .]
”
”
verteilter Stichprobenwert k ∈ H bestimmt, durch k in der folgenden Matrix p[., .]
Stichproben
q
Parameter
1
2
...
k
...
q[1]
1
p[1,1] p[1,2] . . . p[1,k] . . .
q[2]
2
p[2,1] p[2,2] . . . p[2,k] . . .
..
..
..
..
..
..
..
.
.
.
.
.
.
.
q[r]
r
p[r,1] p[r,2] . . . p[r,k] . . .
Γ
m
H
p[1,m]
p[2,m]
..
.
p[r,m]
eine Spalte p[., k], als Kandidat für die Posteriori-Verteilung h[., k] (an der Stelle k) festgelegt. Zur Bestimmung von h[., k] wird jedes Element p[i, k] des Spaltenvektors p[., k]
mit dem entsprechenden Element q[i] des Vekors q (Priori-Verteilung) multipliziert. Normiert man den so entstehenden Spaltenvektor derart, daß dessen Spaltensumme gleich
1 ist, so ist mit dem so bestimmten Vektor


h[1, k]


..
h[., k] := 

.
h[r, k]
(4.17)
die Posteriori-Verteilung an der Stelle k gefunden. Schließlich wird im Sinne des Iterationsprinzips der Vektor q (bisherige Priori-Verteilung) durch den die Posteriori-Verteilung
an der Stelle k beschreibenden Vektor h[., k] überschrieben:
q[.] := h[., k]
(4.18)
20
KAPITEL 4. STATISTIK
h[.,k] übernimmt nun die Funktion der Priori-Verteilung.
Dieser Algorihmus ist, wie in Abschnitt 4.5 bereits erwähnt, in dem statistischen Analyseprogramm umgesetzt.
21
KAPITEL 4. STATISTIK
4.7 Untersuchung der Beispielprogramme
Für die weitere Datenanalyse wurden einige repräsentative Programme bzw. deren Quellcode verwendet. Die Quellcodes wurden teilweise aus größeren firmeninternen Programmen der Entwicklungsabteilung CC/ESM der Robert Bosch GmbH in Stuttgart (Bosch)
oder aus frei verfügbaren Quellen im Internet gewonnen.
Dazu gehören http://sourceforge.net und http://freshmeat.net. Anzumerken ist,
daß insbesondere der Quellcode der firmeninternen Programme der Robert Bosch GmbH
nicht nach außen getragen wurde, sondern nur die Ergebnisse der analysierten Daten
weiterverwendet wurden.
4.7.1 Beispielprogramme
Für die Datenanalyse wurden folgende Java-Programme verwendet, die sich auch auf der
beiliegenden DVD befinden (ausgenommen die Programme der Robert Bosch GmbH):
Programm
Beschreibung
JUnit 3.8.2
Test-Framework für Java-Programme
JHotDraw 6.0b1
GUI framework for Graphics
J2SDK 1.4.2
Java Software Development Kit
Sinaxe2
Code Generator
Apache Ant 1.7.0
Java-based build tool
Apache James 2.3.1
Plattformunabhängiger E-Mail-Server
Apache Tomcat 6.0.10
Web-Server
CoBrake
Tool zur Bremsenauslegung (Bosch)
Frinika
Music workstation software
JCommon 1.0.12
Basis von JFreeChart/JFreeReport
JFreeChart 1.0.6
Grafik-Bibliothek
JFreeReport 0.8.7
Reporting library for embedded solutions
Orson 0.5.0
Collection of charting components
JToolChain
API zur Fernsteuerung von Simulink
SimServ
Simulationsdatenbank-Server (Bosch)
SWTSwing-3-2-0004
Widget-Bibliothek
TAP 1.0.0
Typ-Analyse-Plug-in
Java Chess 0.1.0
Schachprogramm
Kaffe 1.1.7
Clean room impl. of the Java VM
Marathon 1.0.4
GUI development tool
Tabelle 4.1: Repräsentative Beispielprogramme
22
KAPITEL 4. STATISTIK
4.7.2 Untersuchung
Die Programme werden dazu innerhalb der Eclipse-IDE geladen, auf Fehlerfreiheit bezüglich der Syntax geprüft und anschließend der Typ-Analyse unterzogen. Die Quellen
von Bosch wurden firmenintern der Typ-Analyse unterzogen und nur die Ergebnisse hier
weiterverwendet. Dabei entsteht bei jeder Typ-Analyse eine Tabelle der nachfolgenden
beispielhaften Form:
Anzahl der Deklarationen
Typ
11
java.lang.String
6
java.util.List<java.io.File>
4
void
3
java.io.File
3
int
3
java.lang.String[]
2
int[]
1
FileFinder
1
char[]
1
java.lang.Integer
1
java.util.Stack<java.io.File>
1
boolean
0
java.util.ArrayList<java.io.File>
0
IFileFinder
0
StartFileFinder
0
StartFileFinder.LocalClass
Tabelle 4.2: Beispieltabelle eines kleinen Beispielprogramms
Die vorhergehenden Daten stammen aus einem kleinen Testprogramm, welches sämtliche Java-Quelldateien eines Eclipse-Projekts ermittelt. Dieses Testprojekt wurde auch
dazu benutzt, um das Typ-Analyse-Plug-in auf die Korrektheit der Ausgaben zu prüfen.
Hierzu wurden sämtliche möglichen Typ-Konstrukte implementiert und anschließend auf
korrekte Erkennung der Typen hin analysiert.
In der ersten Zeile steht der Datentyp mit dem häufigsten Vorkommen (Deklarationen), in der zweiten Zeile der Datentyp mit dem zweithäufigsten Vorkommen usw. Am
Ende der Liste kann es noch zu Einträgen mit der Anzahl von 0 Deklarationen geben.
Diese deuten auf Datentypen im Programm hin, die dort zwar definiert werden, aber
nie als Deklarationselement verwendet werden. In Java-Programmen kann dies z.B. die
Klasse mit dem Einsprungspunkt zum Hauptprogramm main()“ sein. Diese Klassen ha”
ben keinen Einfluß auf die weitere Analyse, sollen aber bei der Quellcodeanalyse nicht
unberücksichtigt bleiben. Evtl. können auch hier weitere Optimierungen des Programms
erfolgen, indem solche Klassen einfach weggelassen werden können. Für die weitere Analyse wird pro zu analysierendem Programm eine Text-Datei erzeugt, die nur die Anzahl
23
KAPITEL 4. STATISTIK
der aufgetretenen Typen auflistet. Die Namen der einzelnen Typen sind hier nicht von
Bedeutung und wurden in den erzeugten TXT-Dateien einfach weggelassen. Der Inhalt
der TXT-Datei ist nach der Anzahl der Deklarationen in absteigender Reihenfolge sortiert. Diese Datei kann grafisch als Histogramm in folgender Form dargestellt werden:
Abbildung 4.2: Histogramm
Die Daten des Histogramms (TXT-Datei) dienen im Weiteren als Eingabedaten für
das statistische Auswerte-Programm.
24
5 Ergebnisse
5.1 Verteilungen
Die vorliegenden Beispielprogramme aus der Tabelle 4.1 wurden mit dem statistischen
Auswerteprogramm untersucht. In sämtlichen Fällen ergibt sich ein eindeutiges Ergebnis
zugunsten einer der beiden bekannten Verteilungen. Das heißt, die Daten der untersuchten Beispielprogramme fallen eindeutig in eine Klasse der beiden bekannten Verteilungen.
Als Beispiel sei hier die Abbildung 5.1 des Programms JUnit 3.8.2“ gegeben.
”
Abbildung 5.1: Posteriori-Verteilung (JUnit 3.8.2)
Damit lassen sich die Typ-Häufigkeiten des Programms JUnit 3.8.2“ eindeutig der
”
Yule-Verteilung zuordnen, wie man an dem roten Peak erkennen kann.
25
KAPITEL 5. ERGEBNISSE
Abbildung 5.2: Posteriori-Verteilung (JFreeChart 1.0.6)
In diesem Beispiel der Grafikbibliothek JFreeChart 1.0.6“ hat sich die Zipf/Estoup”
Verteilung durchgesetzt, wie man an dem magenta Peak erkennen kann.
26
KAPITEL 5. ERGEBNISSE
Abbildung 5.3: Posteriori-Verteilung (TAP 1.0.0)
In diesem Beispiel von TAP 1.0.0“ hat sich in der Tendenz die Yule-Verteilung durch”
gesetzt, wie man an dem größeren, ausgeprägteren der beiden Peaks erkennen kann.
27
KAPITEL 5. ERGEBNISSE
Für die weiteren Beispielprogramme ergeben sich die in Tabelle 5.1 dargestellten Klassifizierungen. Ein X“ bedeutet hier, daß sich ein eindeutiges Ergebnis in Form eines
”
Peaks bei der Posteriori-Verteilung ergibt. Damit ist das untersuchte Programm eindeutig der jeweiligen Verteilung zuzuordnen.
Programm
Yule
JUnit 3.8.2
X
JHotDraw 6.0b1
J2SDK 1.4.2
Sinaxe2
X
Apache Ant 1.7.0
X
Apache James 2.3.1
X
Apache Tomcat 6.0.10
CoBrake
Frinika
JCommon 1.0.12
X
JFreeChart 1.0.6
JFreeReport 0.8.7
X
Orson 0.5.0
X
JToolChain
X
SimServ
X
SWTSwing-3-2-0004
TAP 1.0.0
X
Java Chess 0.1.0
X
Kaffe 1.1.7
Marathon 1.0.4
X
Zipf/Estoup
X
X
X
X
X
X
X
x
X
Tabelle 5.1: Klassifizierung der Verteilungen
Wie man sehen kann, gibt es ein Programm, nämlich das Typ-Analyse-Plug-in TAP
1.0.0“ selbst, mit dem die statistischen Daten gewonnen wurden, welches die Merkmale
beider Verteilungen aufweist. Details sind in der Grafik 5.3 weiter unten zu sehen. Durch
das große X“ soll aber wiederum der Vorzug für die Yule-Verteilung dargestellt werden.
”
Dieser resultiert von dem ausgeprägteren Peak. Dieses Ergebnis kann damit erklärt werden, daß die beiden bekannten Verteilugen recht ähnlich sind und das Programm TAP,
im Vergleich zu den anderen Programmen, als klein angesehen werden kann. Es besteht
aus nur 14 Java-Quellen mit insgesamt 129 verschiedenen Typen. Größere Programme
bestehen aus über 600 Java-Quellen mit über 1000 Typen, wobei sich statistisch gesehen
ein eindeutigeres und aussagekräftigeres Ergebnis erzielen läßt.
28
KAPITEL 5. ERGEBNISSE
5.2 Abweichungen
In der Tabelle 5.2 sind die Abweichungen der einzelnen Programme von der empirischen
Verteilung aufgelistet. Bei den untersuchten Testprogrammen konnten die folgenden
Abweichungen von der empirischen Verteilung festgestellt werden. Diese Abweichungen bestätigen außerdem die in der Tabelle 5.1 festgestellten Klassifizierungen durch
die Posteriori-Verteilungen (Peaks). Das heißt auch, daß die geringere Abweichung die
Posteriori-Verteilung in vollem Umfang bestätigt. Die geringere Abweichung ist in fetter
Schrift dargestellt.
Programm
JUnit 3.8.2
JHotDraw 6.0b1
J2SDK 1.4.2
Sinaxe2
Apache Ant 1.7.0
Apache James 2.3.1
Apache Tomcat 6.0.10
CoBrake
Frinika
JCommon 1.0.12
JFreeChart 1.0.6
JFreeReport 0.8.7
Orson 0.5.0
JToolChain
SimServ
SWTSwing-3-2-0004
TAP 1.0.0
Java Chess 0.1.0
Kaffe 1.1.7
Marathon 1.0.4
Abweichung Yule
Abweichung Zipf/Estoup
0.18635056631801772
0.2139252939932779
0.22475110504797988
0.19012227629943218
1.1855550352648667
0.784984972715766
0.36653506158059607
0.37747787816560896
0.5533452634033342
0.6244172885230729
0.15808007731559603
0.19031069755143099
1.2659252244811419
0.7469863583426389
1.3943195295211803
0.6590067230093477
0.4206676390460549
0.41466480798539784
0.39069265595919156
0.40685801818957307
0.4419640338985785
0.41114473045336075
0.35488294577760193
0.37578013951639283
0.47358322548335999
0.49268899326698157
0.38237538640069363
0.39626730822490724
0.26056854371873894
0.2795288613168352
0.5170534440285449
0.5039709870349337
0.2852650188290128
0.31588253726842336
0.24328093517665073
0.2671864112061283
1.184271073756466
0.7899465773548795
0.19592428024892475
0.2091552766634423
Tabelle 5.2: Abweichungen der Beispielprogramme
5.3 Fazit
Wie man aus den beiden Tabellen 5.1 und 5.2 sehen kann, ergibt sich keine eindeutige
Mehrheit für eine der beiden Verteilungen. Man kann also feststellen, daß sich für die
hier untersuchten Programme kein eindeutiges Ergebnis zugunsten einer der beiden Verteilungen ergeben hat. Um herauszufinden, welche Faktoren die Entscheidung zugunsten
der einen oder der anderen Verteilung beeinflussen, sind weitere Arbeiten notwendig, die
29
KAPITEL 5. ERGEBNISSE
wohl mit Unterstützung der Fachbereiche Mathematik bzw. Linguistik durchzuführen
wären.
30
6 Typ-Analyse-Plug-in (TAP)
6.1 Anforderungen
Das hier zu entwickelnde Typ-Analyse-Plug-in hat als Hauptaufgabe das Finden sämtlicher in Kapitel 3.2 genannten Deklarationselemente eines Java-Programms. Hierzu muß
der jeweilige AST der Java-Quelle, unter Eclipse auch Compilation-Unit“ genannt, aus”
gewertet werden. Die in diesen Elementen vorkommenden Typen werden erfasst und pro
Typ die Häufigkeit seines Vorkommens bezogen auf alle in der untersuchten Java-Quelle
vorkommenden Deklarationselemente festgehalten. Das Ergebnis wird anschließend tabellarisch und grafisch ausgegeben. Als weitere Anforderung, neben der eben beschriebenen globalen“ Typ-Analyse, ist von Interesse, in welchen anderen Typen ein bestimmter
”
Typ verwendet wird. Das heißt, es wird dargestellt, in welchen anderen Typen ein bestimmter Typ vorkommt. Dies stellt sozusagen eine Detailierung für einen bestimmten,
vom Anwender ausgewählten Typ dar. Hierzu wird im Plug-in eine Auswahl angeboten,
die diese Auswertung möglich macht. Zum besseren Verständnis soll das folgende kleine
Beispiel dienen.
Der Typ java.lang.String“ sei insgesamt z.B. sechs mal in einem Programm enthalten,
”
was die globale Typ-Analyse ergeben hat. Das Programm selbst besteht wiederum aus
den drei Typen, hier z.B. aus den Klassen A, B und C. Der Typ java.lang.String“ ist
”
nun folgendermaßen in den drei Typen/Klassen verteilt:
Typ Anzahl der Vorkommen
A
1
B
3
C
2
Tabelle 6.1: Beispiel von Typ-Vorkommen
Hieraus ist ersichtlich, wie sich die Verwendung des Typs java.lang.String“ detailiert
”
auf die drei ihn benutzenden Typen/Klassen A, B und C verteilt. Dieses Ergebnis kann
für die Analyse der Verwendung von Typ-Abhängigkeiten genutzt werden.
Das Ergebnis kann in einer weiteren Ansicht betrachtet werden. Die Ausgabe erfolgt
wieder tabellarisch und grafisch. Als zusätzliches Feature kann jeweils zwischen der Verwendung von Typen in Deklarationen und den Instanziierungen von Typen umgeschaltet
werden. Die Information über die Typ-Instanziierungen kann als Abfallprodukt“ bei der
”
AST-Analyse gewonnen werden. Als weitere Anforderung soll noch eine Übersicht über
alle im Eclipse-Projekt analysierten Java-Quelldateien in Form einer Liste ausgegeben
werden.
31
KAPITEL 6. TYP-ANALYSE-PLUG-IN (TAP)
Für die beschriebenen Anforderungen werden hierfür die folgenden Ansichten (Views)
innerhalb des Plug-ins realisiert:
• Type Diagram View - stellt die NOD- und NOI-Metrik grafisch dar
• Type List View - stellt die NOD- und NOI-Metrik tabellarisch dar
• Detail Diagram View - stellt das Vorkommen eines bestimmten Typs in einem
anderen Typ grafisch dar
• Detail List View - stellt die Details der Vorkommen eines bestimmten Typs in
einem anderen Typ tabellarisch dar
• File List View - stellt die untersuchten Java-Quellen tabellarisch dar
Beim Start eines Analysevorgangs werden diese Views automatisch erzeugt und in den
Vordergrund der Workbench“ innerhalb der Eclipse-IDE gebracht. Diese können vom
”
Anwender nach Belieben angeordnet werden. Für die nun folgenden beispielhaften Darstellungen wurde der Quellcode des Programms JUnit 3.8.2“ verwendet. JUnit ist eine
”
Testumgebung für Java-Programme.
32
KAPITEL 6. TYP-ANALYSE-PLUG-IN (TAP)
6.1.1 Type Diagram View für die grafische Ausgabe der NOD- und
NOI-Metrik
In der Abbildung 6.1 wird für jeden im analysierten Quellcode vorkommenden Typ die
Häufigkeit seiner Verwendung dargestellt. Die Häufigkeit kann an der y-Achse, die mit
Number“ bezeichnet ist, abgelesen werden. Der eigentliche Typ wird in diesem Dia”
gramm als Nummer angegeben, deshalb ist die x-Achse mir Type#“ bezeichnet. Der
”
genaue Typ kann anhand der Nummer im sogenannten Type List View“ nachgelesen
”
werden. Dort hat jeder Eintrag in der Liste eine eindeutige Nummer, die den jeweiligen Typ repräsentiert. Eine andere Möglichkeit ist die Aktivierung des implementierten
Tooltips, welches erscheint, wenn der Benutzer längere Zeit mit dem Mauszeiger auf einem Balken verweilt. Die Typen werden nach der Häufigkeit ihres Auftretens sortiert,
das heißt, der am häufigsten vorkommende Typ steht ganz links und der am wenigsten
auftretende Typ ganz rechts.
Abbildung 6.1: Histogramm der Häufigkeit der Vorkommen von Typen innerhalb von
JUnit 3.8.2
Durch das Umschalten, mittels I“ in der Menüzeile dieser Ansicht, kann hier auf die
”
Darstellung der Metrik NOI gewechselt werden. Diese gibt die Häufigkeit der Vorkommen
von Instanziierungen von Typen an.
33
KAPITEL 6. TYP-ANALYSE-PLUG-IN (TAP)
Die nun folgende Tabelle zeigt die Daten des obigen Ergebnisses nochmals in gekürzter
tabellarischer Form. Die Tabelle wird zur weiteren Verarbeitung ebenfalls als TXT- und
XLS-Datei von dem Plug-in ausgegeben.
Typ
NOD NOI
void
617
0
java.lang.String
264
0
int
187
0
junit.framework.Test
128
0
boolean
76
0
junit.framework.TestResult
69
22
java.lang.Object
51
7
java.lang.Class
45
0
junit.samples.money.IMoney
45
0
java.util.Vector
35
21
java.util.Enumeration
28
0
junit.samples.money.Money
25
42
java.lang.String[]
25
6
long
25
0
junit.framework.TestSuite
23
32
junit.framework.TestCase
22
0
java.lang.Throwable
21
0
java.awt.Component
17
0
java.awt.GridBagConstraints
16
16
java.awt.event.ActionEvent
16
0
javax.swing.Icon
14
0
double
13
0
javax.swing.JButton
12
7
junit.framework.TestFailure
12
3
junit.samples.money.MoneyBag
11
3
javax.swing.JLabel
9
11
java.util.Hashtable
9
7
...
...
0
Tabelle 6.2: Tabelle der Häufigkeit der Vorkommen von Typen innerhalb von JUnit 3.8.2
34
KAPITEL 6. TYP-ANALYSE-PLUG-IN (TAP)
6.1.2 Type List View für die tabellarische Ausgabe der NOD- und
NOI-Metrik
Die Abbildung 6.2 stellt das oben gezeigte Histogramm der NOD-Metrik 6.1 in Form
einer Tabelle dar. Die dargestellten Daten werden außerdem jeweils in einer Datei abgespeichert, um anschließend weiterverarbeitet werden zu können.
Abbildung 6.2: Listen-Ansicht der Deklarationen/Instanziierungen
35
KAPITEL 6. TYP-ANALYSE-PLUG-IN (TAP)
6.1.3 Detail Diagram View für die grafische Ausgabe der
Abhängigkeiten eines bestimmten Typs
Durch Auswahl einer Zeile, z.B. junit.framework.TestResult“ in der vorherigen Ansicht,
”
kann die Häufigkeit des Vorkommens dieses Typs in Deklarationselementen, die in anderen Typen vorkommen, analysiert werden.
Abbildung 6.3: Typ-Abhängigkeiten des Typs junit.framework.TestResult“
”
Durch das Umschalten, mittels I“ in der Menüzeile dieser Ansicht, kann auch hier auf
”
die Vorkommen von Instanziierungen des selektierten Typs in anderen Typen dargestellt
werden.
36
KAPITEL 6. TYP-ANALYSE-PLUG-IN (TAP)
6.1.4 Detail List View für die tabellarische Ausgabe der
Abhängigkeiten eines bestimmten Typs
Die detailierten Daten dieser Analyse können in der folgenden Ansicht 6.4 in tabellarischer Form betrachtet werden. Mit Hilfe dieser Daten könnten nun ebenfalls Optimierungen eines bestimmten Typs vorgenommen werden. Es können zum einen häufig
benutzte Typen bezüglich Laufzeit oder Speicherbedarf optimiert werden oder zum anderen können selten oder nicht benutzte Typen eliminiert bzw. wegoptimiert werden, z.B.
durch Typen aus einer Standardbibliothek ersetzt werden. Außerdem kann man Abhängigkeiten zwischen einzelnen Typen erkennen und hat so frühzeitig die Möglichkeit
abzuschätzen, welchen Einfluß eine Änderungen eines Typs auf die von ihm abhängigen
Typen mit sich bringt. Es kann damit auch der zeitliche Änderungsaufwand bei größeren
Umstellungen in einem Programm abgeschätzt werden.
Abbildung 6.4: Detail-Ansicht der Vorkommen eines bestimmten Typs in anderen Typen
37
KAPITEL 6. TYP-ANALYSE-PLUG-IN (TAP)
6.2 Praktische Umsetzung
Von dem aktuell selektierten Eclipse-Projekt müssen zunächst alle Java-Quellen, die sogenannten Compilation-Units“ (CUs), identifiziert werden. Anschließend wird von jeder
”
Compilation-Unit der zugehörige AST erzeugt. Dies kann durch das folgende beispielhafte Codefragment 6.1 realisiert werden:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public c l a s s ASTHandler {
// Set source file
File file = new File ( " source .java" ) ;
...
// Allocate buffer for file content
char [ ] content = new char [ file . length ( ) ] ;
// Read in file
file . read ( content ) ;
...
// Create new ASTParser
ASTParser astParser = ASTParser . newParser ( AST . JLS3 ) ;
// Set kind of source
astParser . setKind ( ASTParser . K_COMPILATION_UNIT ) ;
// Create fully quallified type names (e.g. "java.lang. String ")
astParser . setResolveBindings ( true ) ;
// Set source contents
astParser . setSource ( content ) ;
// Create the AST
CompilationUnit cu = ( CompilationUnit ) astParser . createAST ( null ) ;
// Create type declaration vistor
TypeDeclarationVisitor tdVisitor = new TypeDeclarationVisitor ( ) ;
// Set visitor
cu . accept ( tdVisitor ) ;
...
}
Listing 6.1: AST-Erzeugung und Parsen einer Java-Quelle
Hier wird beispielhaft gezeigt, wie für die Quelle source.java“ der AST erzeugt und
”
anschließend der eigenen Besucherklasse zugeführt wird. Die Besucherklasse ist dabei
eine durch den Anwender zur Verfügung gestellte Klasse, welche das bekannte Visitor“”
Entwurfsmuster realisiert. Durch den Aufruf der Funktion createAST“ in Zeile 19 wird
”
der AST der Java-Quelle erzeugt. Mit dem Aufruf der Funktion accept()“ in Zeile 23 der
”
Compilation-Unit, mit dem TypeDeclarationVisitor“ als Argument, wird die Analyse“
”
”
der Quelle angestoßen, um an die Informationen aus dem AST zu gelangen, an denen
das eigene Programm interessiert ist. Die Ergebnisse dieses Besuchervorgangs“ können
”
dann zunächst in Tabellen gehalten werden, um nach erfolgreichem Abschluss weiter
verarbeitet zu werden.
38
KAPITEL 6. TYP-ANALYSE-PLUG-IN (TAP)
Der Hauptaufwand steckt dabei in der Klasse TypeDeclarationVisitor“, welche im
”
Rahmen dieser Arbeit enstanden ist und die eigentliche Auswertung der Typen vornimmt. Dazu wird, wie oben bereits erwähnt, das Visitor“-Entwurfsmuster verwendet,
”
um den AST rekursiv zu durchlaufen. Die zu implementierende Besucherklasse muss nun
alle AST-Knoten abfangen“, an denen sie interessiert ist. Dazu müssen die Besucher”
Funktionen, sogenannte Visitor“ implementiert werden. Die folgende Tabelle 6.3 zeigt
”
die zugehörigen Knotentypen, für die Visitor-Funktionen zu realisieren sind:
AST-Knotentyp
VariableDeclarationFragment
ArrayCreation
MethodDeclaration
EnhancedForStatement
TypeDeclaration
WildcardType
Verwendung
Variablen-Deklarationen
Array-Deklarationen
Rückgabetyp und Parametertyp(en)
von Methoden und Konstruktoren
Deklarationen in for“-Schleifen
”
Klassen- bzw. Interface-Deklarationen
sowie Deklarationen von Aufzählungstypen
Variable Anzahl von Parametern (z.B. String ...)
Tabelle 6.3: AST-Knoten die Typ-Deklarationen repräsentieren
Das folgende Listing 6.2 zeigt ein Codebeispiel für die relevanten Deklarationen anhand typischer Fälle.
1
2
3
4
5
6
7
8
public c l a s s publicType {
// TypeDeclaration
private Stack<File> dirs ;
// VariableDeclarationFragment
private int [ ] array ;
// ArrayCreation
...
public boolean outputAllFiles ( int num ) { // MethodDeclaration
f or ( File file : dirs . pop ( ) . listFiles ( ) ) { // Enh. ForStatement
...
}
9
private c l a s s privateType {
// TypeDeclaration
// Konstruktor
private privateType ( String . . . s ) {
// WildcardType
// " String ..." wird als ein Typ "java.lang. String []" gezaehlt !
...
}
...
}
...
10
11
12
13
14
15
16
17
18
19
}
Listing 6.2: Deklarationsbeispiele und deren Zuordnung zu obigen AST-Knotentypen
39
KAPITEL 6. TYP-ANALYSE-PLUG-IN (TAP)
Dieses Programmfragment hat somit als Ergebnis:
Typ
NOD
boolean
1
int
1
int[]
1
java.io.File
1
java.lang.String[]
1
java.util.Stack<java.io.File>
1
void
1
publicType
0
publicType.privateType
0
Tabelle 6.4: NOD des Programmfragments
6.3 Architektur
Das Typ-Analyse-Plug-in wird als Eclipse-Plug-in realisiert. Für die grafische Ausgabe
der Histogramme wird die Grafik-Bibliothek JFreeChart“ verwendet (www.jfree.org
”
und www.jfreechart.org), die auf der Basis JCommon“ aufbaut. Als weiteres Merkmal
”
sei hier noch die Bibliothek JFreeReport“ genannt, die ebenfalls auf JCommon“ aufbaut
”
”
und für die Erstellung von allen möglichen Reports dient. Diese könnten in einer weiteren
Version des Plug-ins zur Anwendung kommen, um die Dokumentation der Histogramme
und die Weiterverarbeitung zu verbessern. Alle übrigen grafischen Elemente sind dem
Standard Widget Toolkit“ (SWT) entnommen.
”
6.4 Material und Methoden
Für die Erstellung des Plug-ins und des Analyse-Tools wurden die folgenden Hilfsmittel
verwendet:
• Eclipse-IDE Version 3.3.0 (Europa)
• JFreeChart-Bibliothek Version 1.0.4
• JCommon-Bibliothek Version 1.0.8
• Launch4j Cross-Plattform für Java-Applikationswrapper Version 3.0.0-pre2
6.5 Eclipse-IDE
Die Eclipse-IDE erlaubt das Erstellen von Java-Applikationen und Plug-ins. Siehe auch
www.eclipse.org.
40
KAPITEL 6. TYP-ANALYSE-PLUG-IN (TAP)
6.6 JFreeChart-Bibliothek
Diese Bibliothek stellt die Funktionalität für das Erstellen von Grafiken jeglicher Art
zur Verfügung. So können z.B. Kuchen-, Balken-, Linien- und Excel-Grafiken erstellt
werden. Für weitere Informationen siehe www.jfree.org und www.jfreechart.org.
6.7 JCommon-Bibliothek
Diese Bibliothek stellt die Grundfunktionalität für die oben genannte Grafikbibliothek
zur Verfügung. Weiterhin ist sie auch Grundlage für das Erstellen von Reports (JFreeReport).
6.8 Launch4j-Applikationswrapper
Dieses Hilfsprogramm erlaubt das Erstellen einer EXE-Datei aus einer von der EclipseUmgebung exportierten JAR-Datei. Dies ist im vorliegenden Fall nur für das statistische
Auswerteprogramm möglich, welches als eigenständige Applikation gestartet wird. Zur
Laufzeit muß für diese Applikation ebenfalls eine Java-Laufzeit-Umgebung (JRE) vorhanden sein. Weitere Informationen können unter http://launch4j.sourceforge.net
erhalten werden.
41
7 Schlußbetrachtungen
7.1 Zusammenfassung
Ziel dieser Arbeit war die Entwicklung eines Plug-ins, welches ein bestehendes JavaProgramm auf die Häufigkeit der Verwendung der im Programm vorkommenden Typen
hin untersucht. Mit dieser Analyse kann man sich einen Überblick über die verwendeten
Typen verschaffen und ggf. Optimierungen vornehmen.
Aufbauend auf den Ergebnissen der Analyse wurden mit Hilfe statistischer Methoden
die (Typ-)Verteilungen in verschiedenen Programmen untersucht und mit bekannten
Verteilungen verglichen. Hier wurde festgestellt, daß sich die von den Beispielprogrammen ergebenden Verteilungen, ausnahmslos den zwei bekannten Verteilungen Yule“ und
”
Zipf/Estoup“ zuordnen lassen. Daß dies so ist, kann aus meiner Sicht als Zufall gewertet
”
werden, denn es hätte sich genausogut eine neue, unbekannte Verteilung ergeben können.
Das Ergebnis ist deshalb auch als eine Überaschung einzustufen, weil sich Verteilungen
von Typen in Java-Programmen wie die Vereilung von Wörtern in beliebigen Texten
verhalten.
7.2 Einsatzmöglichkeiten von TAP
Das Typ-Analyse-Plug-in kann überall dort zum Einsatz kommen, wo der Bedarf an Optimierungen der vorhandenen bzw. benutzten Klassen besteht. Es können zum Beispiel
die Anzahl der Klassen sowie die Relationen untereinander reduziert bzw. vereinfacht
werden. Das Plug-in kann hier bei der Analyse behilflich sein. Die restlichen Schritte, wie
z.B. die Auflösung bzw. Vereinfachung von Typ-Abhängigkeiten, müssen vom Anwender
manuell durchgeführt werden.
7.3 Ausblick
Neben der erfolgten statistischen Untersuchung bezüglich der Verteilung von Typen
könnten noch detailiertere Fragen gestellt werden, die Raum für weiterführende Arbeiten bieten. Dazu gehört zum Beispiel die Frage, wie weit sich die Grammatik“ von
”
Java-Programmen an die Grammatik von normalen“ Texten anlehnt bzw. damit über”
einstimmt. Für den Vergleich der beiden Grammatiken könnte die folgende Zuordnung
zugrunde gelegt werden:
42
KAPITEL 7. SCHLUSSBETRACHTUNGEN
Text-Grammatik Programm-Grammatik
Substantiv
Typ
Adjektiv
Variable
Verb
Methode
Tabelle 7.1: Gegenüberstellung von Grammatiken
Um hierzu eine Aussage zu treffen, müsste man einen Parser für beliebige Texte implementieren, der als Ergebnis ein Histogramm pro Textgruppe liefert. Auf der Programmseite müßte z.B. ein Plug-in entstehen, welches, aufbauend auf dem AST, die Grammatik
des Programms, ebenfalls in Form eines Histogramms, liefert. In einem letzten Schritt
können dann die Ergebnisse miteinander verglichen werden, um eine Aussage über die
Übereinstimmung zu erhalten. Dazu sollten dann aber die Erfahrungen von Linguistikern und Mathematikern von vorneherein mit berücksichtigt werden. Mit dem daraus
sich ergebenden Ergebnis könnte man einen Vergleich zwischen Programm- und Textgrammatik anstellen. Es wäre also eine Aussage möglich, ob sich die beiden Grammatiken
ähnlich sind oder nicht.
7.4 Fazit
Durch diese Arbeit steht ein grundlegendes Werkzeug für die Typ-Analyse von JavaProgrammen zur Verfügung, das für weitere statistische Untersuchungen oder Refactorings von Programmen dienen kann. Hierfür können zum einen die Ausgaben der
Ergebnisse in den Dateien dienen. Zum anderen könnte aber auch noch ein weiterer
Erweiterungspunkt ( Extension-Point“ in Eclipse genannt) in das vorhandene Plug-in
”
eingefügt werden, über den die Daten der Ergebnisse ausgelesen werden können. So
könnten andere Plug-ins bequem auf die Ergebnisse zugreifen.
43
Abbildungsverzeichnis
3.1
3.2
AST-Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
AST-View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
9
4.1
4.2
Statistisches Analyse-Programm . . . . . . . . . . . . . . . . . . . . . . .
Histogramm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
24
5.1
5.2
5.3
Posteriori-Verteilung (JUnit 3.8.2) . . . . . . . . . . . . . . . . . . . . . .
Posteriori-Verteilung (JFreeChart 1.0.6) . . . . . . . . . . . . . . . . . . .
Posteriori-Verteilung (TAP 1.0.0) . . . . . . . . . . . . . . . . . . . . . .
25
26
27
6.1
Histogramm der Häufigkeit der Vorkommen von Typen innerhalb von
JUnit 3.8.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Listen-Ansicht der Deklarationen/Instanziierungen . . . . . . . . . . . . .
Typ-Abhängigkeiten des Typs junit.framework.TestResult“ . . . . . . .
”
Detail-Ansicht der Vorkommen eines bestimmten Typs in anderen Typen
33
35
36
37
6.2
6.3
6.4
A.1 Histogramm der Typ-Instanziierungen . . .
A.2 Plug-in-Detail . . . . . . . . . . . . . . . . .
A.3 Datei-Ansicht des ausgewählten Programms
A.4 Selektion des Exports . . . . . . . . . . . . .
A.5 Ablage der JAR-Datei . . . . . . . . . . . .
A.6 Optionen des Exports . . . . . . . . . . . . .
A.7 Start der Typ-Analyse . . . . . . . . . . . .
A.8 JAR-Export . . . . . . . . . . . . . . . . . .
A.9 Ressourcen und JAR-Dateiname . . . . . . .
A.10 JAR-Packet-Optionen . . . . . . . . . . . .
A.11 JAR-Manifest-Spezifikation . . . . . . . . .
A.12 Grundeinstellungen . . . . . . . . . . . . . .
A.13 Classpath . . . . . . . . . . . . . . . . . . .
A.14 Minimum JRE . . . . . . . . . . . . . . . .
A.15 Start-Fehlermeldung . . . . . . . . . . . . .
44
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
51
52
53
55
56
57
59
70
71
72
73
74
75
76
77
Tabellenverzeichnis
3.1
Auswertung des Beispielcodes . . . . . . . . . . . . . . . . . . . . . . . .
6
4.1
4.2
Repräsentative Beispielprogramme . . . . . . . . . . . . . . . . . . . . .
Beispieltabelle eines kleinen Beispielprogramms . . . . . . . . . . . . . .
22
23
5.1
5.2
Klassifizierung der Verteilungen . . . . . . . . . . . . . . . . . . . . . . .
Abweichungen der Beispielprogramme . . . . . . . . . . . . . . . . . . . .
28
29
6.1
6.2
31
6.3
6.4
Beispiel von Typ-Vorkommen . . . . . . . . . . . . . . . . . . . . . . . .
Tabelle der Häufigkeit der Vorkommen von Typen innerhalb von JUnit
3.8.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
AST-Knoten die Typ-Deklarationen repräsentieren . . . . . . . . . . . .
NOD des Programmfragments . . . . . . . . . . . . . . . . . . . . . . . .
34
39
40
7.1
7.2
Gegenüberstellung von Grammatiken . . . . . . . . . . . . . . . . . . . .
Inhalt der beiliegenden DVD . . . . . . . . . . . . . . . . . . . . . . . . .
43
48
A.1 AST-Knoten, der Typ-Instanziierungen repräsentiert . . . . . . . . . . .
A.2 Beispielprogramm von Typ-Instanziierungen . . . . . . . . . . . . . . . .
A.3 Pakete und Klassen des Typ-Analyse-Plug-ins . . . . . . . . . . . . . . .
50
50
54
45
Listings
3.1
3.2
3.3
Algorithmus zur Berechnung der Metrik NOD . . . . . . . . . . . . . . .
Beispielcode mit relevanten Deklarationselementen . . . . . . . . . . . . .
Beispiel für Besucherfunktionen zum Auswerten von AST-Daten . . . . .
5
6
10
6.1
6.2
AST-Erzeugung und Parsen einer Java-Quelle . . . . . . . . . . . . . . .
Deklarationsbeispiele und deren Zuordnung zu obigen AST-Knotentypen
38
39
A.1 Algorithmus zur Berechnung der Metrik NOI . . . . . . . . . . . . . . . .
A.2 Beispiel für Typ-Instanziierungen . . . . . . . . . . . . . . . . . . . . . .
A.3 Listing des statistischen Auswerteprogramms . . . . . . . . . . . . . . . .
49
50
60
46
Literaturverzeichnis
[1] Martin Äschlimann. org.eclipse.jdt.astview - ast view. 2007.
[2] E. Gamma; K. Beck.
Addison-Wesley, 2004.
Eclipse Erweitern - Prinzipien, Patterns und Plug-ins.
[3] Berthold Daum. Java-Entwicklung mit Eclipse 3.2. dpunkt Verlag, 4. edition, 2006.
[4] WIKIPEDIA Die freie Enzyklopadie; Artikel
http://de.wikipedia.org/wiki/bibliometrie.
zum
Thema
Bibliometrie.
[5] Olivier Thomann (IBM); Thomas Kuhn (Eye Media GmbH). Abstract syntax tree.
Eclipse Corner Articles, November 2006.
[6] Samuel Kotz; Norman L. Johnson. Discrete Distributions. Houghton Mifflin Company Boston, 1969.
[7] J. Hartung; B. Elpelt; K.-H. Klösener. Statistik, volume 13. Oldenbourg, 1993.
[8] Karl-Rudolf Koch. Grundprinzipien der Bayes-Statistik. pages 253–260, 1998.
[9] Philip Mayer. Eine Metrik-Suite zur Analyse des Einsatzes von Interfaces in Java.
2003.
[10] O. Moeschlin; E. Grycko; C. Poppinga. Angewandte Statistik - Vorlesungskript 1361
der FernUniversität in Hagen. 2001.
[11] Eric Clayberg; Dan Rubel. Building Commercial-Quality Plug-ins. Addison Wesley,
2. edition, 2006.
[12] G. Marinell; G. Steckel-Berger. Einführung in die Bayes-Statistik. Oldenburg Verlag, 3. edition, 2001.
[13] O. Moeschlin; F. Steinert. Bayessche Statistik. Birkhäuser Verlag, 1995.
[14] L. Fahrmeir; R. Künstler; I. Pigeot; G. Tutz. Statistik - Der Weg zur Datenanalyse.
Springer Verlag, 5. edition, 2005.
[15] Erich Gamma; Richard Helm; Ralph E. Johnson; John Vlissides. Design Patterns.
Addison-Wesley, 1995.
47
Inhalt der beiliegenden DVD
Verzeichnis
Inhalt
pdf
Master-Arbeit als PDF
latex
LaTeX-Quellen der Master-Arbeit
plugin
Typ-Analyse-Plug-in (TAP)
project/zip
Beispielprogramme
project/txt
Typ-Analyse-Ergebnisse
statistics
Statistisches Auswerteprogramm
eclipse
Eclipse-SDK 3.3 (Europa)
jfree
jcommon 1.0.8
jfree
jfreechart 1.0.4
launch4j
launch4j 3.0.0-pre2
Tabelle 7.2: Inhalt der beiliegenden DVD
48
A Anhang
A.1 Metrik - Number of Instantiations (NOI)
Diese Metrik wird für die aktuelle Arbeit nicht benötigt, kann aber durch einen relativ geringen Zusatzaufwand realisiert werden, da das Grundgerüst der Software dies
erlaubt. Die Metrik mißt die Instanziierungen von Typen in Java-Programmen und kann
folgendermaßen angegeben werden:
N OI(A) = | {new A} |
(A.1)
wobei gilt: A = Typ
Für das Analyse-Plug-in ergibt sich der folgende Algorithmus in Form von Pseudocode:
1
2
3
4
f or each instantiationElement of actualProject do {
Type := getTypeOfInstantiationElement ;
CountingArray [ Type ]++;
}
Listing A.1: Algorithmus zur Berechnung der Metrik NOI
49
ANHANG A. ANHANG
A.2 Ermittlung der Typ-Instanziierungen
Entsprechend der Ermittlung von Deklarationen gibt es auch einen AST-Knotentyp zur
Ermittlung von Typ-Instanziierungen, wie die folgenden Tabelle A.1 zeigt. Diese wurde
für spätere Erweiterungen mit implementiert, da nur ein weiterer Visitor notwendig
wurde.
AST-Knotentyp
Verwendung
ClassInstanceCreation Typ-Instanziierung
Tabelle A.1: AST-Knoten, der Typ-Instanziierungen repräsentiert
Das Listing A.2 zeigt ein Codebeispiel für den typischen Anwendungsfall von TypInstanziierungen.
1
2
3
4
5
6
7
8
9
public c l a s s publicType {
...
public void publicType ( ) {
Integer i = new Integer ( 1 5 ) ;
String s = new String ( "Test" ) ;
List<String> l = new ArrayList<String >() ;
...
}
}
Listing A.2: Beispiel für Typ-Instanziierungen
Bei der Analyse werden alle Vorkommen von Typ-Instanziierungen gezählt, die mit dem
Operator new“ vorgenommen werden. Für die Betrachtungen in dieser Arbeit hat diese
”
Metrik keine Bedeutung. Sie kann sehr leicht als Erweiterung des Typ-Analyse-Plugins implementiert werden, da nur ein einziger neuer Knotentyp ClassInstanceCreation“
”
in die Analyse mit eingebaut werden muß. Der Einfachheit halber wurde sie deshalb
realisiert, um eventuell für weitere Arbeiten als Grundlage zu dienen.
Im Beispiel aus A.2 werden 3 Typen jeweils einmal instanziiert, sodaß das Analyseergebnis wie folgt aussieht:
Typ
Anzahl der Typ-Instanziierungen
Integer
1
String
1
List<String>
1
Tabelle A.2: Beispielprogramm von Typ-Instanziierungen
50
ANHANG A. ANHANG
Für das Programm JUnit 3.8.2“ sieht die Ausgabe für Instanziierungen wie in Abbildung
”
A.1 folgt aus. Der Typ der einzelnen Säulen bleibt dabei unverändert an der gleichen
Position wie bei der Darstellung der NOD-Metrik. Dies bedeutet, man kann einfach
vergleichen, wie oft ein bestimmter Typ in einer Deklaration verwendet bzw. wie oft er
instanziiert wird.
Abbildung A.1: Histogramm der Typ-Instanziierungen
51
ANHANG A. ANHANG
A.3 Typ-Analyse-Plug-in (TAP)
Die folgenden Unterkapitel beschreiben die Installation, Anwendungung, Erstellung und
den Start des Typ-Analyse-Plug-ins.
A.3.1 Installation des Plug-ins
Das vorliegende Plug-in steht als JAR-Archiv zur Verfügung. Der Name lautet
de.feu.cap x.y.z.jar“, wobei x.y.z“ die aktuelle Versionsnummer darstellt. Es muß in das
”
”
Unterverzeichnis plugins“ der Eclipse-Installation abgelegt werden. Nach erfolgreicher
”
Installation sollte sich in der Ansicht Plug-in Details“ der Eclipse-Platform der folgende
”
Eintrag wiederfinden.
Abbildung A.2: Plug-in-Detail
Details zu aktuell installierten Plug-ins kann man durch Aktivierung des Menübefehls
Help->About Eclipse SDK“ und anschließender Selektion der Schaltfläche Plug-in De”
”
tails“ zur Anzeige bringen.
A.3.2 Anwendung des Typ-Analyse-Plug-ins
Die Typanalyse kann mittels rechtem Mausklick auf ein Eclipse-Projekt im Package
”
Explorer“ der Eclipse-Plattform aktiviert werden. Dazu muss das Projekt geöffnet sein.
Der auszuwählende Menüpunkt ist mit Start Type Analysis“ beschriftet und befindet
”
sich am unteren Ende des Popup-Menüs. Anschließend startet die Typanalyse, welche
sämtliche zum Projekt gehörenden Dateien mit der Endung .java“ mit einbezieht.
”
52
ANHANG A. ANHANG
A.3.3 File List View für die Ausgabe aller analysierten Java-Quellen
Die folgende Abbildung A.3 zeigt die Ansicht der Quell-Dateien des aktuell analysierten
Programms. Diese Ansicht dient zur Kontrolle der analysierten Java-Quellen. Dies sind
sämtliche Dateien mit der Endung .java“ des ausgewählten Programms.
”
Abbildung A.3: Datei-Ansicht des ausgewählten Programms
Die dargestellten Dateien wurden für die Analyse herangezogen, indem jeweils ihr zugehöriger AST erzeugt wurde und in diesem nach den relevanten Deklarationselementen
gesucht wurde, die für die Bestimmung der Häufigkeit der Verwendung von Typen herangezogen wurden, siehe auch Kapitel 3.2. Die Informationen werden dabei in Listen
gespeichert. Zum einen wird für jeden Typ die Anzahl seiner Verwendung aufsummiert
und zum anderen wird festgehalten, in welchem anderen Typ der gefundene Typ vorkommt. Mit diesen Informationen sind dann die Ausgaben in den einzelnen Ansichten
möglich, inklusive der Umschaltung zwischen den beiden Metriken NOD und NOI.
53
ANHANG A. ANHANG
A.3.4 Paketstruktur des Plug-ins
Die folgendende Tabelle A.3 zeigt die Paketstruktur des Eclipse-Projekts.
Pakete
de.feu.tap
de.feu.tap.popup.actions
de.feu.tap.views
Klassen
Activator
DetailType
FileFinder
SearchResult
TypeDeclarationVisitor
TypeListElement
TypeNumber
XYBarToolTipGenerator
NewAction
DetailDiagramView
DetailListView
FileListView
TypeDiagramView
TypeListView
Tabelle A.3: Pakete und Klassen des Typ-Analyse-Plug-ins
54
ANHANG A. ANHANG
A.3.5 Erstellen der JAR-Datei
Zuerst muß aus dem durch einen rechten Mausklick auf das geöffnete Eclipse-Projekt
de.feu.tap“ erscheinenden Kontextmenü , der Menüpunkt Export...“ ausgewählt wer”
”
den. Daraufhin startet der Export-Wizard. In der nun folgenden Ansicht muß der dargestellte Eintrag Deployable plug-ins and fragments“ selektiert werden.
”
Abbildung A.4: Selektion des Exports
55
ANHANG A. ANHANG
In der nächsten Ansicht wird der Ort für die zu erzeugende JAR-Datei spezifiziert. Dies
kann entweder ein Verzeichnis (Option Directory“) sein, in dem dann ein Verzeichnis
”
plugins“ erzeugt wird, welches die JAR-Datei enthält. Eine andere Möglichkeit ist die
”
Angabe einer Archivdatei (Option Archive file“), welche dann anschließend das JAR”
Archiv enthält.
Abbildung A.5: Ablage der JAR-Datei
In beiden Fällen wird das für die weitere Arbeit benötigte JAR-Archiv de.feu.tap 1.0.0.jar“
”
erzeugt.
56
ANHANG A. ANHANG
Im letzten Schritt sollten noch die Einstellungen auf der Registerkarte Options“ über”
prüft werden und sichergestellt werden, daß für das Plug-in ein individuelles JAR-Archiv
erzeugt wird.
Abbildung A.6: Optionen des Exports
A.3.6 Hinzufügen der JFreeChart-Bibliotheken
Um die JFreeChart-Bibliotheken hinzufügen zu können, muß das JAR-Archiv mit WinZip geöffnet werden. Anschließend müssen die entpackten JFreeChart-Bibliotheken manuell dem Archiv hinzugefügt werden. Hierbei handelt es sich um die beiden JARs
jcommon-1.0.8.jar“ und jfreechart-1.0.4.jar“ Dies geschieht am einfachsten mittels
”
”
Drag&Drop des entpackten Unterverzeichnisses org“ der beiden Bibliotheken in das
”
57
ANHANG A. ANHANG
geöffnete WinZip. Beim Entpacken der beiden JARs entsteht ein gemeinsames Unterverzeichnis, in dem die kompletten Bibliotheken enthalten sind. Wichtig ist hierbei, daß
die bereits im JAR-Archiv des Plug-ins enthaltene Datei MANIFEST.MF“, im Unter”
verzeichnis meta-inf“, nicht mit der gleichnamigen Datei der JFreeChart-Bibliothek
”
überschrieben wird. Im Normallfall warnt WinZip standardmäßig vor dem Überschreiben. Die gleichnamige Datei MANIFEST.MF“ der Grafik-Bibliothek kann einfach ge”
löscht werden, da sie nicht benötigt wird. Dies vermeidet den angesprochenen Konflikt.
A.3.7 Ausgaben des Typ-Analyse-Plug-ins
Zur Ausgabe der Analyseergebnisse werden in der aktuellen Version 1.0.0 die folgenden
Dateiformate verwendet:
• TXT - enthält die sortierten Typ-Vorkommen ohne Namen im Text-Format
• XLS - enthält die sortierten Typ-Vorkommen inklusive Namen im Excel-Format
Diese Dateien können für die Weiterverarbeitung in anderen Programmen dienen. Mit
der XLS-Datei besteht außerdem die Möglichkeit, die Histogramme in Excel darzustellen. Zusätzlich enthält sie auch die kummulierten und auf die Gesamtsumme aller Typvorkommen normierten Summen der einzelnen Typ-Vorkommen, die für weitergehende
Darstellungen/Berechnungen dienen können.
58
ANHANG A. ANHANG
A.3.8 Start der Typ-Analyse
Zum Start der Typ-Analyse muß man wie folgt vorgehen. Zunächst öffnet man mit einem
rechten Mausklick auf ein geöffnetes Eclipse-Projekt das zugehörige Kontextmenü, dargestellt in Abbildung A.7. Dieses enthält einen Menüpunkt zum Starten der Typanalyse.
Nach Auswahl dieses Menüpunktes werden nach einer Bearbeitungszeit, abhängig von
der Größe des Projekts, automatisch die fünf vordefinierten Ansichten in der EclipseWorkbench angezeigt. Falls die Analyse für ein anderes Projekt gestartet wird, so werden
alle Daten und Grafiken automatisch aktualisiert.
Abbildung A.7: Start der Typ-Analyse
59
ANHANG A. ANHANG
A.4 Statistisches Auswerteprogramm
A.4.1 Listing des Programms
1
2
/* Java - Programm zur Bestimmung der Posteriori - Wahrscheinlichkeit
und der Dichtefunktion */
package de . feu . bayeschart ;
3
4
5
6
7
8
import
import
import
import
import
java . awt . Color ;
java . awt . GridLayout ;
java . io . BufferedReader ;
java . io . FileReader ;
java . io . IOException ;
9
10
import javax . swing . JOptionPane ;
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import
import
import
import
import
import
import
import
import
import
import
import
import
import
org . jfree . chart . ChartFactory ;
org . jfree . chart . ChartPanel ;
org . jfree . chart . JFreeChart ;
org . jfree . chart . axis . NumberAxis ;
org . jfree . chart . plot . PlotOrientation ;
org . jfree . chart . plot . XYPlot ;
org . jfree . chart . renderer . xy . XYLineAndShapeRenderer ;
org . jfree . chart . title . TextTitle ;
org . jfree . chart . title . Title ;
org . jfree . data . xy . XYDataset ;
org . jfree . data . xy . XYSeries ;
org . jfree . data . xy . XYSeriesCollection ;
org . jfree . ui . ApplicationFrame ;
org . jfree . ui . RefineryUtilities ;
26
27
28
29
/* Applikation zur Anzeige von zwei Liniencharts
basierend auf der Klasse XYDataset */
public c l a s s BayesChart extends ApplicationFrame {
30
31
32
33
34
35
36
37
38
39
40
41
private s t a t i c int anz = 0 ;
private s t a t i c f i n a l int Npar = 1 0 0 ;
private s t a t i c f i n a l int num = 6 ;
private s t a t i c String dataFile = null ;
s t a t i c double [ ] [ ] K = null ;
s t a t i c double [ ] prior = new double [ 2 ∗ Npar + 1 ] ;
s t a t i c double [ ] post = new double [ 2 ∗ Npar + 1 ] ;
s t a t i c double [ ] rho = new double [ 2 ∗ Npar + 1 ] ;
s t a t i c int [ ] sam = null ;
s t a t i c double [ ] rh = null ;
s t a t i c double [ ] cof = new double [ num ] ;
60
ANHANG A. ANHANG
42
43
44
45
46
char ch ;
int gammaoptYule = 0 ;
int gammaoptZipf = 0 ;
double diffYule = 0 . 0 ;
double diffZipf = 0 . 0 ;
47
48
private s t a t i c f i n a l long serialVersionUID = 1L ;
49
50
51
/* Erzeugt eine neue Applikation */
public BayesChart ( f i n a l String title ) {
52
super ( title + " - [" + dataFile . toString ( ) + "]" ) ;
getContentPane ( ) . setLayout (new GridLayout ( 1 , 2 ) ) ;
53
54
55
f i n a l XYDataset dataset1 = createDataset1 ( ) ;
f i n a l XYDataset dataset2 = createDataset2 ( ) ;
f i n a l JFreeChart chart1 = createChart1 ( dataset1 ) ;
f i n a l JFreeChart chart2 = createChart2 ( dataset2 ) ;
f i n a l ChartPanel chartPanel1 = new ChartPanel ( chart1 ) ;
f i n a l ChartPanel chartPanel2 = new ChartPanel ( chart2 ) ;
chartPanel1 . setPreferredSize (new java . awt . Dimension ( 5 0 0 , 3 5 0 ) ) ;
chartPanel2 . setPreferredSize (new java . awt . Dimension ( 5 0 0 , 3 5 0 ) ) ;
getContentPane ( ) . add ( chartPanel1 ) ;
getContentPane ( ) . add ( chartPanel2 ) ;
56
57
58
59
60
61
62
63
64
65
66
}
67
68
69
70
/* Ezeugt ein neues Linienchart fuer die Dichtefunktionen
beiden Verteilungen basierend auf einem XYDataset */
private JFreeChart createChart1 ( f i n a l XYDataset dataset ) {
71
72
73
74
75
76
77
78
79
80
81
// Neues Chart erzeugen
f i n a l JFreeChart chart = ChartFactory . createXYLineChart (
"Yule -/ Zipf -Estoup - Verteilung " , // chart title
"rho" ,
// x axis label
" Wahrscheinlichkeit " ,
// y axis label
dataset ,
// data
PlotOrientation . VERTICAL ,
// vertical orientation
true ,
// include legend
false ,
// tooltips
false ) ;
// urls
82
83
84
Title subTitle = new TextTitle ( " Posteriori " ) ;
chart . addSubtitle ( subTitle ) ;
85
86
87
// Einstellungen fuer das Chart vornehmen
chart . setBackgroundPaint ( Color . white ) ;
61
ANHANG A. ANHANG
88
f i n a l XYPlot plot = chart . getXYPlot ( ) ;
plot . setBackgroundPaint ( Color . lightGray ) ;
plot . setDomainGridlinePaint ( Color . white ) ;
plot . setRangeGridlinePaint ( Color . white ) ;
89
90
91
92
93
f i n a l XYLineAndShapeRenderer renderer = new
XYLineAndShapeRenderer ( ) ;
renderer . setSeriesShapesVisible ( 0 , f a l s e ) ;
renderer . setSeriesShapesVisible ( 1 , f a l s e ) ;
renderer . setSeriesPaint ( 0 , Color . red ) ;
renderer . setSeriesPaint ( 1 , Color . magenta ) ;
plot . setRenderer ( renderer ) ;
94
95
96
97
98
99
100
// Beide Achsen auf Integer - Anzeigewerte umstellen
f i n a l NumberAxis rangeAxis = ( NumberAxis ) plot . getRangeAxis ( ) ;
rangeAxis . setStandardTickUnits ( NumberAxis .
createIntegerTickUnits ( ) ) ;
f i n a l NumberAxis domainAxis = ( NumberAxis ) plot . getDomainAxis
() ;
domainAxis . setStandardTickUnits ( NumberAxis .
createIntegerTickUnits ( ) ) ;
101
102
103
104
105
106
return chart ;
107
108
}
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* Ezeugt ein neues Linienchart fuer die Anzeige der
Posteriori - Verteilungen basierend auf einem XYDataset */
private JFreeChart createChart2 ( f i n a l XYDataset dataset ) {
// Neues Chart erzeugen
f i n a l JFreeChart chart = ChartFactory . createXYLineChart (
" Analysedaten - vs. Opt.- Verteilung " , // chart title
" Typen " ,
// x axis label
" Wahrscheinlichkeit " ,
// y axis label
dataset ,
// data
PlotOrientation . VERTICAL ,
// vertical orient .
true ,
// include legend
false ,
// tooltips
false ) ;
// urls
123
124
125
Title subTitle = new TextTitle ( "Delta: [Yule ]=" + diffYule + "
[Zipf - Estoup ]=" + diffZipf ) ;
chart . addSubtitle ( subTitle ) ;
126
127
128
// Einstellungen fuer das Chart vornehmen
chart . setBackgroundPaint ( Color . white ) ;
62
ANHANG A. ANHANG
129
f i n a l XYPlot plot = chart . getXYPlot ( ) ;
plot . setBackgroundPaint ( Color . lightGray ) ;
plot . setDomainGridlinePaint ( Color . white ) ;
plot . setRangeGridlinePaint ( Color . white ) ;
130
131
132
133
134
f i n a l XYLineAndShapeRenderer renderer = new
XYLineAndShapeRenderer ( ) ;
renderer . setSeriesShapesVisible ( 0 , f a l s e ) ;
renderer . setSeriesShapesVisible ( 1 , f a l s e ) ;
renderer . setSeriesShapesVisible ( 2 , f a l s e ) ;
renderer . setSeriesPaint ( 0 , Color . blue ) ;
renderer . setSeriesPaint ( 1 , Color . red ) ;
renderer . setSeriesPaint ( 2 , Color . magenta ) ;
plot . setRenderer ( renderer ) ;
135
136
137
138
139
140
141
142
143
// Beide Achsen auf Integer - Anzeigewerte umstellen
f i n a l NumberAxis rangeAxis = ( NumberAxis ) plot . getRangeAxis ( ) ;
rangeAxis . setStandardTickUnits ( NumberAxis .
createIntegerTickUnits ( ) ) ;
f i n a l NumberAxis domainAxis = ( NumberAxis ) plot . getDomainAxis
() ;
domainAxis . setStandardTickUnits ( NumberAxis .
createIntegerTickUnits ( ) ) ;
144
145
146
147
148
149
return chart ;
150
151
}
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/* Einsprungpunkt main des Statistikprogramms */
public s t a t i c void main ( f i n a l String [ ] args ) {
// Check file name
i f ( args . length == 0 ) {
JOptionPane . showMessageDialog ( null
, "No command line argument (data filename ) specified !\n
Please specify the data filename as the only argument "
, " Bayes chart " , JOptionPane . ERROR_MESSAGE ) ;
} else {
// Speichern des TXT - Dateinamens
dataFile = args [ 0 ] ;
// TXT - Datei einlesen
readFile ( args [ 0 ] ) ;
// Daten bestimmen
calcData ( ) ;
// Bestimmung der Posteriori - Wahrscheinlichkeit
estimateData ( ) ;
170
63
ANHANG A. ANHANG
// Neue Charts erzeugen
f i n a l BayesChart demo = new BayesChart ( "Bayes Chart" ) ;
demo . pack ( ) ;
RefineryUtilities . centerFrameOnScreen ( demo ) ;
demo . setVisible ( true ) ;
171
172
173
174
175
}
176
177
}
178
179
180
181
182
/* Berechnung der Gamma - Funktion . Es wird der
Logarithmus der Gamma - Funktion berechnet */
public s t a t i c double LNGamma ( double xx ) {
double x , y , ser , tmp ;
183
cof [ 0 ] = 7 6 . 1 8 0 0 9 1 7 2 9 4 7 1 4 6 ;
cof [ 1 ] = −86.50532032941677;
cof [ 2 ] = 2 4 . 0 1 4 0 9 8 2 4 0 8 3 0 9 1 ;
cof [ 3 ] = −1.231739572450155;
cof [ 4 ] = 0 . 1 2 0 8 6 5 0 9 7 3 8 6 6 1 7 9 E −2;
cof [ 5 ] = −0.5395239384953 E −5;
x = xx ;
y = x;
tmp = x + 5 . 5 ;
tmp = tmp − ( x + 0 . 5 ) ∗ Math . log ( tmp ) ;
ser = 1 . 0 0 0 0 0 0 0 0 0 1 9 0 0 1 5 ;
f or ( int j = 0 ; j < num ; j++) {
y = y + 1.0;
ser = ser + cof [ j ] / y ;
}
return −tmp + Math . log ( 2 . 5 0 6 6 2 8 2 7 4 6 3 1 0 0 0 5 ∗ ser / x ) ;
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
}
201
202
203
204
205
206
/* Berechnung der Beta - Funktion mit Hilfe der Gamma - Funktion .
Man beachte , dass der Logarithmus der Gamma - Funktion
verwendet wird */
public s t a t i c double Beta ( double a , double b ) {
double expo ;
207
expo = LNGamma ( a ) + LNGamma ( b ) − LNGamma ( a + b ) ;
return Math . exp ( expo ) ;
208
209
210
}
211
212
213
214
215
216
/* Einlesen der Daten aus der TXT - Datei in das Feld sam */
private s t a t i c void readFile ( String dataFile ) {
// Pruefen des Dateinamens der TXT - Datei
i f ( dataFile != null ) {
// Erzeuge buffered reader
64
ANHANG A. ANHANG
BufferedReader br = null ;
try {
// Oeffne buffered reader
br = new BufferedReader (new FileReader ( dataFile ) ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
try {
int lineNumber = 0 ;
// Berechne Zeilenanzahl der TXT - Datei
while ( br . readLine ( ) != null ) {
lineNumber++;
}
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// Puffer allokieren entsprechen der Zeilenanzahl ;
sam = new int [ lineNumber ] ;
K = new double [ 2 ∗ Npar + 1 ] [ lineNumber ] ;
rh = new double [ lineNumber ] ;
anz = lineNumber ;
231
232
233
234
235
236
// Oeffne neuen buffered reader
br = new BufferedReader (new FileReader ( dataFile ) ) ;
// Lese Anzahl der Zeilen
f or ( int i = 0 ; i < lineNumber ; i++) {
sam [ i ] = Integer . valueOf ( br . readLine ( ) ) . intValue ( ) ;
}
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
try {
// Schliesse buffered reader
br . close ( ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
}
252
253
}
254
255
256
257
258
/* Berechnung der Normalverteilung */
private s t a t i c void calcData ( ) {
int i , j ;
double sum ;
259
260
261
262
sum = 0 . 0 ;
f or ( i = 0 ; i < anz ; i++) {
rh [ i ] = sam [ i ] ;
65
ANHANG A. ANHANG
sum = sum + rh [ i ] ;
263
}
264
265
f or ( i = 0 ; i < anz ; i++) {
rh [ i ] = rh [ i ] / sum ;
}
266
267
268
269
f or ( i = −Npar ; i <= Npar ; i++) {
prior [ i + Npar ] = 1 . 0 / ( 2 . 0 ∗ Npar + 1 . 0 ) ;
}
270
271
272
273
f or ( i = −Npar ; i <= Npar ; i++) {
rho [ i + Npar ] = Math . abs ( i / ( double ) Npar ∗ 5 . 0 ) ;
}
274
275
276
277
/* Berechnung der Koeffizienten der Matrix K
Vergleiche auch Rekursionsalgorithmus */
// ZIPF/ ESTOUP
f or ( i = 0 ; i <= Npar ; i++) {
sum = 0 . 0 ;
f or ( j = 0 ; j < anz ; j++) {
K [ i + Npar ] [ j ] = 1 . 0 / Math . exp ( rho [ i + Npar ] ∗ Math . log ( j
+ 1) ) ;
sum = sum + K [ i + Npar ] [ j ] ;
}
f or ( j = 0 ; j < anz ; j++) {
K [ i + Npar ] [ j ] = K [ i + Npar ] [ j ] / sum ;
}
}
278
279
280
281
282
283
284
285
286
287
288
289
290
291
// YULE
f or ( i = −Npar ; i <= −1; i++) {
sum = 0 . 0 ;
f or ( j = 0 ; j < anz ; j++) {
K [ i + Npar ] [ j ] = Beta ( j + 1 . 0 , rho [ i + Npar ] + 1 . 0 ) ;
sum = sum + K [ i + Npar ] [ j ] ;
}
f or ( j = 0 ; j < anz ; j++) {
K [ i + Npar ] [ j ] = K [ i + Npar ] [ j ] / sum ;
}
}
292
293
294
295
296
297
298
299
300
301
302
303
}
304
305
306
307
/* Anwendung der Summenformel des Satzes von Bayes
Bestimmung der Posteriori - Wahrscheinlichkeit */
s t a t i c void estimateData ( ) {
66
ANHANG A. ANHANG
int i , j , gamma ;
double sum ;
308
309
310
f or ( i = anz − 1 ; i >= 0 ; i−−) {
f or ( j = 1 ; j < sam [ i ] ; j++) {
sum = 0 . 0 ;
f or ( gamma = −Npar ; gamma <= Npar ; gamma++)
post [ gamma + Npar ] = K [ gamma + Npar ] [ i ] ∗
Npar ] ;
sum = sum + post [ gamma + Npar ] ;
}
f or ( gamma = −Npar ; gamma <= Npar ; gamma++)
post [ gamma + Npar ] = post [ gamma + Npar ] /
}
prior = post ;
}
}
311
312
313
314
315
316
317
318
319
320
321
322
323
324
{
prior [ gamma +
{
sum ;
}
325
326
327
328
329
330
/* Erzeugen der Datensaetze fuer die Dichtefunkionen */
private XYDataset createDataset1 ( ) {
int gamma ;
double xk , yk ;
double yscale = Npar ;
331
f i n a l XYSeries series1 = new XYSeries ( "Yule" ) ;
f or ( gamma = −Npar ; gamma <= −1; gamma++) {
xk = rho [ gamma + Npar ] ;
yk = Math . round ( post [ gamma + Npar ] ∗ yscale ) ;
series1 . add ( xk , yk ) ;
}
332
333
334
335
336
337
338
f i n a l XYSeries series2 = new XYSeries ( "Zipf - Estoup " ) ;
f or ( gamma = 0 ; gamma <= Npar ; gamma++) {
xk = rho [ gamma + Npar ] ;
yk = Math . round ( post [ gamma + Npar ] ∗ yscale ) ;
series2 . add ( xk , yk ) ;
}
339
340
341
342
343
344
345
f i n a l XYSeriesCollection dataset = new XYSeriesCollection ( ) ;
dataset . addSeries ( series1 ) ;
dataset . addSeries ( series2 ) ;
return dataset ;
346
347
348
349
350
}
351
352
/* Erzeugen der Datensaetze fuer die Posteriori - Wahrscheinlich -
67
ANHANG A. ANHANG
353
354
355
356
357
358
359
360
keiten , basierend auf den Analysedaten . Bestimmen des
jeweiligen Optimums fuer rho */
private XYDataset createDataset2 ( ) {
int gamma ;
int i ;
double xk , yk ;
double max ;
double scale = Npar ∗ 2 0 ;
361
362
363
364
365
366
367
368
max = 0 . 0 ;
f or ( gamma = −Npar ; gamma <= −1; gamma++) {
i f ( post [ gamma + Npar ] > max ) {
max = post [ gamma + Npar ] ;
gammaoptYule = gamma + Npar ;
}
}
369
370
371
372
373
374
375
376
377
378
max = 0 . 0 ;
f or ( gamma = 0 ; gamma <= Npar ; gamma++) {
i f ( post [ gamma + Npar ] > max ) {
max = post [ gamma + Npar ] ;
gammaoptZipf = gamma + Npar ;
}
}
System . out . println ( "Rho[ GammaOptYule ] := " + rho [ gammaoptYule
]) ;
System . out . println ( "Rho[ GammaOptZE ]
:= " + rho [ gammaoptZipf
]) ;
379
380
381
382
383
384
385
386
scale = anz ∗ 3 0 . 0 ;
f i n a l XYSeries series1 = new XYSeries ( " Analysedaten " ) ;
f or ( i = 0 ; i < anz ; i++) {
xk = i + 1 ;
yk = Math . round ( scale ∗ rh [ i ] ) ;
series1 . add ( xk , yk ) ;
}
387
388
389
390
391
392
393
f i n a l XYSeries series2 = new XYSeries ( "Opt. Yule" ) ;
f or ( i = 0 ; i < anz ; i++) {
xk = i + 1 ;
yk = Math . round ( scale ∗ K [ gammaoptYule ] [ i ] ) ;
series2 . add ( xk , yk ) ;
}
394
395
396
f i n a l XYSeries series3 = new XYSeries ( "Opt. Zipf/ Estoup " ) ;
f or ( i = 0 ; i < anz ; i++) {
68
ANHANG A. ANHANG
xk = i + 1 ;
yk = Math . round ( scale ∗ K [ gammaoptZipf ] [ i ] ) ;
series3 . add ( xk , yk ) ;
397
398
399
}
400
401
/* Berechnung des Deltas zwischen opt. Verteilung und den
Analysedaten */
f or ( i = 0 ; i < anz ; i++) {
diffYule += Math . abs ( rh [ i ] − K [ gammaoptYule ] [ i ] ) ;
diffZipf += Math . abs ( rh [ i ] − K [ gammaoptZipf ] [ i ] ) ;
}
402
403
404
405
406
407
System . out . println ( " Delta[Yule ]=" + diffYule ) ;
System . out . println ( " Delta[Zipf ]=" + diffZipf ) ;
408
409
410
f i n a l XYSeriesCollection dataset = new XYSeriesCollection ( ) ;
dataset . addSeries ( series1 ) ;
dataset . addSeries ( series2 ) ;
dataset . addSeries ( series3 ) ;
return dataset ;
411
412
413
414
415
}
416
417
}
Listing A.3: Listing des statistischen Auswerteprogramms
69
ANHANG A. ANHANG
A.4.2 Erstellen des Eclipse-Projekts
Das statistischen Auswerteprogramm wird aus dem, auf der beiliegenden DVD verfügbaren ZIP-Archiv bayeschart.zip“ als Projekt in Eclipse importiert. Dazu muss zuerst
”
ein leeres Java-Projekt erzeugt werden. Anschließend kann das ZIP-Archiv in das neue
Projekt importiert werden.
A.4.3 Erstellen der JAR-Datei
Zum Erzeugen der EXE-Datei des statistischen Auswerteprogramms muß zunächst eine
JAR-Datei exportiert werden. Dies geschieht mit dem Export-Wizard aus Eclipse heraus.
Er wird mit einem rechten Mausklick auf das geöffnete Programm gestartet ( Export...“).
”
Danach erscheint das folgende Fenster.
Abbildung A.8: JAR-Export
70
ANHANG A. ANHANG
Hier muss die Option JAR file“ ausgewählt werden. Im nächsten Schritt werden die
”
Komponenten selektiert, die im Export enthalten sein sollen. Hier nur die auf der linken
Seite vorhandene Ressource de.feu.bayeschart“ selektieren. Auf der rechten Seite alle
”
Dateien deselektieren, da hier für die Datensicherung des Programms bereits Dokumente
und fertige JAR- bzw. EXE-Dateien gesichert wurden. Weiter unten im Fenster muß das
Ausgabeverzeichnis inklusive JAR-Dateiname spezifiziert werden.
Abbildung A.9: Ressourcen und JAR-Dateiname
71
ANHANG A. ANHANG
Im nächsten Schritt sollten keine Veränderungen vorgenommen werden.
Abbildung A.10: JAR-Packet-Optionen
72
ANHANG A. ANHANG
Im letzten Schritt muß das bereits existierende Manifest MANIFEST.MF“ ausgewählt
”
werden, welches den Klassenamen enthält, der die Methode main“ beinhaltet, die dann
”
beim Start der EXE ausgeführt wird.
Abbildung A.11: JAR-Manifest-Spezifikation
Mit Auswahl der Schaltfläche Finish“ wird die JAR-Datei im angegebenen Verzeichnis
”
erstellt. Nun muß ebenfalls, wie bei der Plug-in-Erstellung vom Typ-Analyse-Plug-in
bereits beschrieben, die Grafik-Bibliothek manuell zu der JAR-Datei hinzugefügt werden.
Dieser Schritt ist bereits im Kapitel A.3.6 beschrieben worden. Der Ablauf ist aber
derselbe ohne Änderungen im Ablauf.
73
ANHANG A. ANHANG
A.4.4 Erstellen der EXE-Datei
Mit dem Freeware-Tool Launch4j“ (Applikations-Wrapper) kann die vorher erzeugte
”
JAR-Datei in eine EXE-Datei umgewandelt werden. Hierzu sind die folgenden Schritte
notwendig.
Abbildung A.12: Grundeinstellungen
Hier die zu erstellende EXE-Datei spezifizieren und das vorhandene JAR auswählen.
74
ANHANG A. ANHANG
Bei der folgenden Ansicht müssen keine Änderungen vorgenommen werden. Der sogenannte Classpath“ wird automatisch aus der Manifest-Datei MANIFEST.MF“ des
”
”
JARs bezogen.
Abbildung A.13: Classpath
75
ANHANG A. ANHANG
Bei dieser Ansicht muß die Minimalversion des Java Runtime Environments“ (JRE)
”
spezifiziert werden. Für die verwendete Grafik-Bibliothek JFreeChart 1.0.8“ inklusive
”
JCommon 1.0.4“ muss die minimale JRE-Version 1.3.0 betragen. Bei zukünftigen Wei”
terentwicklungen der JFreeChart-Bibliothek kann sich dies zu einer höheren Version hin
ändern.
Abbildung A.14: Minimum JRE
Nach dem Start des Build-Wrappers wird die EXE-Datei durch die Auswahl der Zahnrad”
Ikone“ in der Button-Bar erzeugt. Es sollten sich die gleichen Ausgaben, wie im Fenster
mit der Bezeichnung Log“ dargestellt, ergeben. Die Einstellungen können auch in einer
”
XML-Datei abgelegt werden, um beim nächsten Erstellen nicht wieder neu eingegeben
76
ANHANG A. ANHANG
werden zu müssen. Zum Test kann die generierte EXE-Datei sofort mit einem Doppelklick gestartet werden. Dies sollte die nachstehende Fehlermeldung zur Folge haben,
da kein Kommandozeilenargument angegeben wurde. Man kann dann aber trotzdem von
einer korrekten Erstellung der EXE-Datei ausgehen.
Abbildung A.15: Start-Fehlermeldung
77
Erklärung
Hiermit erkläre ich, daß ich die vorliegende Abschlussarbeit selbstständig verfaßt, noch
nicht anderweitig für Prüfungszwecke vorgelegt, keine anderen als die angegebenen Quellen und Hilfsmittel benutzt, sowie wörtliche und sinngemäße Zitate als solche gekennzeichnet habe.
Stuttgart, den 26. Februar 2008
——————————————–
Gerd Eichhorn
78
Herunterladen