Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Bytecodemanipulation

Ähnliche Präsentationen


Präsentation zum Thema: "Bytecodemanipulation"—  Präsentation transkript:

1 Bytecodemanipulation
Vortrag im Rahmen des Seminars Generatives Computing Ronald Kutschke Daniel Haag Mirko Bleyh Markus Block

2 Übersicht Motivation Classfile Format Java Virtual Machine
[ Einleitung ] Übersicht Motivation Classfile Format Java Virtual Machine Möglichkeiten Vor- / Nachteile Beispiel: Framework BCEL Weitere Anwendungsgebiete Fazit Quellen

3 Motivation Warum Bytecodemanipulation? Kein Sourcecode vorhanden
[ Einleitung ] Motivation Warum Bytecodemanipulation? Kein Sourcecode vorhanden Änderung am Bytecode einfacher, als am Sourcecode Wieso kommt jemand auf die Idee den Bytecode abändern zu wollen? Am Sourcecode rumzuschrauben ist doch viel einfacher, weil man ihn im Klartext lesen kann. Ich habe darauf zwei Antworten gefunden: Zum einen kann es sein, dass der Sourcecode eines Classfiles nicht vorliegt, aber eine Anpassung z.B. an ein Framework erfolgen muss, zum anderen wenn es leichter ist den compilierten Code statt den Sourcecode zu ändern. Sourcecode ist eigentlich einfach nur Text, wenn man etwas ändern möchte muss man den Text parsen, um z.B. an eine bestimmte Methode zukommen. Der Bytecode wurde vom Compiler schon geparst, d.h. die Methoden, Felder, usw. stehen an definierten Stellen im Bytecode. Bytecode kann auf zwei Arten manipuliert werden, zum einen kann das Classfile von der Festplatte gelesen, dann geändert und anschließend wieder auf der Festplatte abgespeichert werden. Zum anderen kann ein Classloader beim Einlesen der Klasse den Bytestrom abändern und dann der VM übergeben.

4 Classfile Format [ Classfile Format ]
Wenn ich ein Classfile editieren möchte, muss ich wissen wie der Java Compiler die Classfiles in das Dateisystem ablegt. Der Compiler speichert jede Klassendefinition in einer eigene Datei. Das ist jetzt nichts spektakuläres, aber daran muss man denken, wenn man mit inneren Klassen zu tun hat, die tauchen nämlich als eigene Classfiles auf.

5 Aufbau [ Classfile Format ]
Bevor wir uns ein Classfile im Hexeditor ansehen ein kleiner Überblick über das Classfileformat. Im Detail gehe ich noch auf die wesentlichen Elemente ein. Ein Classfile fängt immer mit einer festen Sequenz von 4 Bytes an, der magicnumber, danach folgen 4 Byte mit Versionsangaben zu dem Format des Classfiles. Danach folgt zuerst die Angabe über die Anzahl der Einträge im Constantpool und direkt im Anschluss daran der Constantpool. Was genau der Constantpool ist, erkläre ich gleich noch. Die Accessflags zeigen an ob die Klasse public, final ist, oder ob es sich um ein Interface oder eine abstrakte Klasse handelt. This_Class gibt die eigene Klasse an, Super_Class die Klasse von der geerbt wird, wird von keiner Klasse geerbt, ist java/lang/Object die Superklasse. Dann werden Interfaces aufgeführt, die implementiert werden, im Anschluss daran werden die Fields der Klasse aufgeführt, dann folgen die Methoden der Klasse und als letztes werden Attribute der Klasse angegeben.

6 Beispiel (1) [ Classfile Format ]
Für das Besipiel habe ich ein einfaches HelloWorld ausgesucht, das mit javac compiliert wird. Als nächstes öffne ich das Classfile in einem Hexeditor.

7 Beispiel (2) [ Classfile Format ]
Die Darstellung ist etwas langweilig, unübersichtlich, deshalb ->

8 Beispiel (3) [ Classfile Format ]
habe ich die verschiedenen Teile des Classfiles eingefärbt und die Abbildung vom Aufbau daneben gestellt. Wie schon erwähnt startet ein Classfile immer mit einer magic_number, das sind die ersten 4 Byte. Wie wir von Java gewöhnt sind hat das auch was mit Kaffee zu tun nämlich „CAFEBABE“. Danach folgt die Version Angabe zum Format des Classfiles, das sind die nächsten 4 Bytes. Darauf folgt die Anzahl der Einträge im Constantpools, das sind die nächsten 2 Bytes 22(Hex) = 34 und darauf folgt der Constantpool mit seinen Einträgen. Die Länge des Constantpools ist nicht angegeben, sie lässt sich nur ermitteln, indem man den kompletten Constantpool durchläuft und die Länge jedes Eintrags ermittelt. Die Accessflags zeigen an dass die Klasse public. This_Class referenziert den zweiten Eintrag im Constantpool, das müsste dann eine Klassendefinition unserer Klasse HelloWorld sein. Super_Class verweist auf den vierten Eintrag im Constantpool, da unsere HelloWorld Klasse von keiner Klasse explizit erbt, ist java/lang/Object die Superklasse, das heisst, der vierte Eintrag im Constantpool müsste eine Klassendefinition der Klasse java/lang/Object sein. Dann werden Interfaces aufgeführt, die implementiert werden, in unserem Fall gibt es keine, deshalb fällt der Teil Interfaces weg. Im Anschluss daran werden die Fields der Klasse aufgeführt, auch hier fällt der Teil Fields weg, da es keine Fileds in unserer Klasse gibt. Dann folgen die Methoden der Klasse, in unserem Beispiel sind es zwei, einmal die main Methode und der Default Konstruktor, der immer vorhanden ist und als letztes werden Attribute der Klasse angegeben. Im Beispiel ist das einzige Attribut die zugehörige Sourcecode Datei. Denkbar wäre, dass man selbst Attribute zum Classfile hinzufügen könnte, wie z.B. eine Klasse als Serializable kennzeichnen. Soviel ich weiss ist das bisher nicht möglich. Aber vielleicht weiss da jemand mehr? .Net benutzt so einen Mechanismus. Wie man schon sehen kann, ist der Constantpool der grösste Teil des Classfiles, deshalb ist der Constantpool ein ganz zentraler Bestandteil des Classfiles, hier werden Informationen abgelegt, die dann aus dem ganzen Classfile referenziert werden. Vorstellen kann man sich den Constantpool wie eine Tabelle, jeder Eintrag in dieser Tabelle kann über seinen Index abgerufen werden. Einträge sind z.B: sämtliche Klassennamen die im Sourcecode vorkommen alle mit Packageangabe im Stil java/lang/Object, der Name der Superklasse, Name des Classfiles, Name der Java Sourcecode Datei, Interfacenamen, Strings, Variablennamen... Wichtig der Name Constant bedeutet nicht, dass hier Java Konstanten abgelegt werden

9 Constantpool (1) [ Classfile Format ]
Jeder Constantpooleintrag kann eine eigene Struktur haben, die wie folgt aussieht: Das erste Byte zeigt den Typ des Eintrags an, alle Bytes die danach folgen, hängen vom Typ des Eintrags ab. Es gibt verschiedene Eintragstypen, ein paar habe ich in der Tabelle aufgeführt.

10 Constantpool (2) [ Classfile Format ]
Ein Eintrag vom Typ UTF8 hat als erstes Byte 01, danach folgt die Längenangabe des Strings und anschließend der Inhalt des Strings. In unserem Beispiel ist der UTF8 String 10 Byte lang und hat den Inhalt „HelloWorld“.

11 Constantpool (3) [ Classfile Format ]
Der zweite Eintrag im Constantpool ist vom Typ Class. Die Struktur des Class Typs sieht folgendermaßen aus: Das erste Byte gibt den Typ an, im Beispiel 07, die nächsten zwei Bytes geben den Index des Klassennamens im Constantpool an, im Beispiel 01. Hier wird also eine Klasse mit dem Namen HelloWorld definiert.

12 Inhalt Constantpool [ Classfile Format ]
BaseType Character Type Interpretation B byte signed byte C char Unicode character D double double-precision floating-point value F float single-precision I int integer J long long integer L<classname>; reference an instance of class <classname> S short signed short V void Return type void Z boolean true or false [ one array dimension Wir könnten weiter Byte für Byte das Classfile durchgehen, nur macht das wahrscheinlich wenig Sinn, deshalb gibt es Tools, die den Inhalt des Constantpool komplett auflisten. Hier sieht man den Inhalt des Constantpools. this_class hatte den zweiten Eintrag referenziert, also die Klassendefinition HelloWorld, super_class hatte den vierten Eintrag referenziert, die Klassendefinition von java/lang/Object. Ein paar kleine Anmerkungen: Klassennamen im Bytecode werden immer mit dem Packagenamen angegeben und nicht wie gewohnt mit einem Punkt als Trennzeichen sondern einem Slash. Eintrag 3. Referenzdatentypen fangen, wie man in der Tabelle sieht mit einem L an, dann kommt der Klassenname und am Schluss ein Strichpunkt. Im Constantpool sieht man das am Eintrag 13. Arrays werden mit einer offenen eckigen Klammer angegeben Eintrag 31. Übergabeparameter einer Methode werden in einer Klammer angegeben, Eintrag 15, hier ein String Array, der Rückgabewert steht hinter der Klammer, hier ein V, das bedeutet void. Aus diesem String wird später im Classfile die Methodensignatur der main-Methode zusammengebaut, public static void main(String[] args) Der Konstruktor wird mit <init> bezeichnet Interessant ist noch die Art und Weise, wie Methoden definiert werden. In unserer HelloWorld Klasse rufen wir System.out.println(String s) auf, das bedeutet wir bekommen von der Klasse System über die Klassenvariable out eine Instanz der Klasse PrintStream. Auf diesem Objekt verwenden wir die Methode println, die einen String als Übergabeparameter erwartet und keinen Rückgabewert hat. Um die Methode println() in unserer Klasse nutzen zu können, muss sie im Constantpool definiert werden und das sieht folgendermaßen aus: Zuerst werden zwei UTF8 Strings definiert Index 26 und 27, anschließend wird ein Eintrag vom Typ NameAndType definiert, der auf Index 26 als Name und 27 als Übergabeparameter und Rückgabewert verweist. Eintrag mit dem Index 29 vom Typ Methodref verweist auf die Klasse, zu der die Methode gehört und auf eine Struktur vom Typ NameAndType.

13 Methodendefinition [ Classfile Format ]
Hier sieht man den Aufbau der Methoden Definition nochmal etwas übersichtlicher. Wie man in diesem einfachen Beispiel sieht ist das Classfile nicht kompliziert zu verstehen, trotzdem muss man beim editieren von Classfiles ein paar Dinge beachte. Wenn man z.B. nur eine Methode einfügen möchte, müssen entsprechende Definitionen im Constantpool eingefügt werden, constantpool count, method count müssen geändert werden und dann muss die eigentliche Methode im Bereich Methods eingefügt werden.

14 Security [ Classfile Format ] class Login{
private String passwort = “xyz“; ... public void login(String eingabe){ if(passwort.equals(eingabe)) { //login durchführen } Was mich an dieser Stelle etwas überrascht hat, war, dass Strings im Bytecode nicht irgendwie besonders codiert werden, sondern lesbar im Bytecode abgespeichert werden. Man benötigt also noch nicht einmal einen Decompiler, um die Strings einer Klasse lesen zu können. BEISPIEL class Login{ private String passwort = “xyz“; public void login(String eingabe){ if(passwort.equals(eingabe)) { //login } Klar, dass das Passwort ein String unter hunderten sein kann, aber aus dem Blickwinkel der Security zählt nicht ob es umständlich ist, sondern nur ob es möglich das Passwort in so einem Classfile herauszufinden. Der Bytecode ist also überhaupt nicht verschlüsselt oder sonstwie geschützt, nur weil man ihn nicht sofort ohne Probleme lesen kann bedeutet dies noch kein Schutz! Auch der Quellcode ist nach dem Compiliervorgang nicht wirklich geschützt. Ein Decompiler kann aus einem Classfile wieder ein Sourcecodefile erstellen. Wenn ich einen Algorithmus entwickelt habe, dessen Quellcode ich nicht veröffentlichen möchte, dann kann ich nicht einfach das compilierte Classfile herausgeben. Ich benötige in diesem Fall spezielle Tools, die es einem Decompiler erschweren eine vernünftige Sourcecodedatei zu erstellen.

15 Optimierung (1) [ Classfile Format ]
Hier nochmal der Aufbau des Classfiles. Hier handelt es sich eigentlich nur um ein HelloWorld Beispiel, die Dimensionen, welcher Teil verbraucht den meisten Platz, ist allerdings auf andere Classfiles übertragbar.

16 Optimierung (2) [ Classfile Format ]
Diese Grafik stammt aus einem Paper „Analysis of the Java Class File“ und zeigt die durchschnittliche Grössen der einzelnen Classfile Komponenten. Aus dem Blickwinkel von Optimierung könnte man sich fragen was alles dazu beiträgt, dass der Constantpool grösser wird und nicht unbedingt notwendig wäre. Das wären zum Beispiel lange Namen von Variablen, Methoden, usw... Hier gibt es Tools, die den Bytecode entsprechend bearbeiten und den Variablen, Methoden, usw... neue, kurze Namen geben. Der java Compiler fügt auch Debuginformationen in den Bytecode ein. Wenn eine Applikation allerdings fertig entwickelt ist, werden diese Informationen eigentlich nicht mehr benötigt, stehen aber trotzdem im Bytecode. Auch hier gibt es Tools, die diese Informationen entfernen.

17 Java Virtual Machine Zentrales Element der Java Technologie
[ JVM ] Java Virtual Machine Zentrales Element der Java Technologie Verantwortlich für Plattform-Unabhängigkeit Abstrakte Rechenmaschine mit fester Anzahl an Instruktionen (Opcodes), die auf verschiedenen Speicherbereichen operiert Kennt keine Java Programmiersprache, lediglich das Bytecode-Format Kann in Hardware oder in Software realisiert werden

18 JVM Details Spezifizierte Aufgaben einer JVM:
Lesen von Bytecode Ausführen der definierten Operationen  Alles weitere ist dem Entwickler überlassen, also z.B. Speicheranordnung der Runtime Data Areas Algorithmus der Garbage-Collection Ausführungsart der Operationen (Interpretieren oder in nativen Code kompilieren und dann ausführen)

19 [ JVM ] JVM-Architektur

20 Motivation Speicherort der Klassen kann sehr unterschiedlich sein:
[ Class Loader ] Motivation Speicherort der Klassen kann sehr unterschiedlich sein: Lokales Dateisystem Entferntes Dateisystem Datenbank Internet Zentraler Punkt zum Laden von Klassen  Erhöhte Sicherheit

21 Aufgaben Um eine Klasse verwenden zu können, muss Folgendes von der
[ Class Loader ] Aufgaben Um eine Klasse verwenden zu können, muss Folgendes von der VM bzw. dem Class Loader erledigt werden: Dynamisches Laden der Klasse: Finden der binären Repräsentation der Klasse (Bytecode) und erzeugen einer Klasse aus diesem Linken der Klasse: Verifizieren Reservieren und Initialisieren von Speicher für Klassenvariablen Transformieren von symbolischen Referenzen in direkte Referenzen Initialisieren der Klasse: Ausführen der <clinit> Methode der Klasse, Initialisieren der Klassenvariablen

22 Bootstrap Class Loader
Problem: Der Class Loader selber ist auch eine Java Klasse! Wer lädt diesen? Antwort: Der Bootstrap Class Loader: Er ist Teil der JVM Er ist zumeist in der selben Sprache wie die VM geschrieben Wird beim Hochfahren der VM geladen Lädt alle weiteren Class Loader und die Klassen des Java API Nur vom ihm geladene Klassen werden als vertrauenswürdig eingestuft JDK1.1: Benötigt unter Windows die CLASSPATH Umgebungsvariable JDK1.2: System Class Loader durchsucht den CLASSPATH selber

23 [ Class Loader ] public class SimpleClassLoader extends ClassLoader {
public synchronized Class loadClass(String name, boolean resolve) { Class c = findLoadedClass(name); if (c != null) return c; try { c = findSystemClass(name); } catch (ClassNotFoundException e) {} RandomAccessFile file = new RandomAccessFile("test/" + name + ".class", "r"); byte data[] = new byte[(int)file.length()]; file.readFully(data); c = defineClass(name, data, 0, data.length); } catch (IOException e) {} if (resolve) resolveClass(c); return c; }

24 Parent Delegation Model
[ Class Loader ] Parent Delegation Model Bezeichnet die Arbeitsteilung der verschiedenen Class Loader innerhalb einer JVM: Seit JDK 1.2 vorgeschlagen, bereits in java.lang.ClassLoader realisisert Jeder Class Loader besitzt Referenz auf Parent (ausser BCL) Anfrage zum Laden einer Klasse wird immer erst an den Parent weitergegeben Wenn Parent Klasse nicht finden, versucht es der CL selber

25 [ JVM ] JVM-Architektur

26 [ Runtime Data Areas ] Method Area: Enthält alle Klassen-Informationen (Name, Superklasse, Constant Pool, Methoden-Informationen und –Bytecode, Exception-Table, Klassenvariablen, etc.) Gehört logisch zum Heap Heap: Hier werden alle Objekt-Instanzen und Array gespeichert (d.h. Objekt-Referenzen zeigen auf Speicherbereiche im Heap): Instanzvariablen der Klasse des Objekts und aller Superklassen Zeiger auf den Speicherbereich der Klassendaten in der Method Area Für alle Threads gemeinsam

27 PC Register: Native Method Stack: Jeder Thread hat eigenen PC Register
[ Runtime Data Areas ] PC Register: Jeder Thread hat eigenen PC Register PC Register ist ein Wort groß Enthält „Adresse“ (nativer Pointer oder Offset des Bytecodes) der aktuell ausführenden Instruktion bzw. ist undefiniert beim Ausführen von nativem Code Native Method Stack: Führt Programm-Code aus, der nicht in Java geschrieben ist Optional

28 Java Stack: Jeder Thread hat eigenen Stack
[ Runtime Data Areas ] Java Stack: Jeder Thread hat eigenen Stack Nur zwei mögliche Operationen: PUSH und POP Stack besteht aus einzelnen Stack Frames: zu jeder Methode gibt es einen Frame immer genau ein Frame ist aktuell (aktuelle Methode) bei Methodenaufruf wird ein Frame erzeugt und zum neuen aktuelle Frame am Stack (push) bei Methodenende (return oder Exception) wird der aktuelle Frame verworfen und der vorherige Frame wird zum aktuellen Frame (pop) ein Thread kann nur auf seinen Stack zugreifen !

29 Stack Frame Lokale Variablen: Operanden-Stack: Frame Daten:
[ Runtime Data Areas ] Stack Frame Lokale Variablen: Als 0-basiertes Array aus Wörtern organisiert Enthält Parameter und lokale Variablen der jeweiligen Methode Operanden-Stack: Als 0-basiertes Array aus Wörtern organisiert Lediglich PUSH und POP erlaubt (keine Indizierung möglich!) Hauptspeicherort von Operanden für Instruktionen Frame Daten: Referenz auf Constant Pool der Klasse der Methode Daten zur Wiederherstellen des vorherigen Frames bei normalem Methodenende Exception Behandlung (Referenz auf Exception-Table der Methode) Weitere Daten...

30 [ JVM ] JVM-Architektur

31 3 unterschiedliche Bedeutungen:
[ Execution Engine ] 3 unterschiedliche Bedeutungen: Abstrakte Spezifikation: für jede Bytecode Instruktion wird spezifiziert, was gemacht werden soll, aber nicht wie! Konkrete Implementierung: Interpretation, JIT-Kompilierung, etc. Laufzeit-Instanz: Jeder Thread ist eine Instanz einer Execution Engine

32 Implementierungen Interpretation Just-in-Time Kompilierung
[ Execution Engine ] Implementierungen Interpretation sehr einfach (1. Generation der VMs) Just-in-Time Kompilierung 1. Ausführung einer Methode → nativer Code Adaptive Optimierung Mischung aus Interpretation und JIT Kompilierung Code-Ausführung wird beobachtet % der CPU Zeit → % des Codes wird z.B. in Suns HotSpot VM verwendet

33 Funktionsweise der JVM
Applet Demo...

34 Möglichkeiten Einfügen von Debuginformationen
Einfügen von Tracinginformationen Besseres Handling von NullPointerExceptions Umbenennen von Variablen- und Methodennamen um Bytecode unleserlich zu machen (Obfuskator) Einfügen von Code zur Serialisierung (JDO) Bytecodeoptimierung Debug / Trace  siehe Beispiel Exceptions: bei jedem return prüfen ob object null ist und wenn ja dann gleich dort Exception werfen  umgehen des nichts sagenden stack trace Umbenennen: Um Reverse Engineering zu erschweren (Dekompilieren) JDO (Java Data Objects) die Persistenz wird komplett nach dem Kompilieren eingefügt. Optimierung  Constant Pool verkleinern

35 Vorteile Sourcecode muss nicht vorliegen
[ Vor- / Nachteile ] Vorteile Sourcecode muss nicht vorliegen Code kann dynamisch zur Ladezeit verändert werden Einfügen von fest vorgegebenem Code, der von Programmierern nicht verändert werden kann Source  Veränderungen nach Compile-Time Ladezeit  Über eigenen ClassLoader (siehe Beispiel) Fester Code  Programmier kann nicht vergessen diesen Code einzufügen (z.B. Logging)

36 Nachteile Aufwändig Fehler erscheinen erst zur Laufzeit
[ Vor- / Nachteile ] Nachteile Aufwändig Genaue Kenntnis des Classfile-Formats, der Opcodes und der VM sind Voraussetzung Fehlen von Kommentaren Fehler erscheinen erst zur Laufzeit Aufwändig  neue, komplexe Sprache muss gelernt werden. Kommentare  entfallen beim Kompilieren Laufzeitfehler  Keine Entdeckung von Kompiler (immer unschön)

37 Byte Code Engineering Library (BCEL)
Objektorientierte Bearbeitung des prozeduralen Bytecodes Mappen sämtlicher Opcodes in Java Klassen Getrennte Packages zum Analysieren und Inspizieren Modifizieren und Erzeugen Manipulation nach der Compile- oder zur Ladezeit Bytecode Verifier Disassembler BCEL Jakarta Apache Project Darstellung des Classfiles in Javaobjekt. Trennung Analyse, Generator Verifier  soll Laufzeitfehler vermeiden Dissambler  stellt Classfile als HTML dar, in der die Referencen aufgelöst und verlinkt sind ( Bytecodeviewer) Benutzt von: Xalan XSLT-Prozessor, AspectJ, JBOSS und verschiedene JDO implementationen

38 Verwendung von BCEL Einlesen und parsen des Classfiles -> JavaClass
Auslesen der Klassenparameter (Methoden, Constant Pool, Felder, …) Generatoren der Klassenparameter erzeugen Manipulation über die Generator Objekte Ersetzen der alten Parameter durch die neuen aus den Generatorobjekten Zurückschreiben des Classfiles auf Festplatte Was muss ich Tun, um mit BCEL den Bytecode eines Classfiles zu manipulieren Einlesen aus Datei oder Byte[] möglich Auslesen aus JavaClass erlaubt die Analyse Generatorobjekte erlauben Manipulation Manipulation: Einfügen, ändern von Feldern, Methoden, Methodenaufrufen, Variablennamen Generatorobjekte können wieder in JavaClass gesetzt werden. Zurückschreiben nur wenn die Klasse persistent geändert werden soll ansonsten übergabe als Byte[] an Classloader

39 Aufruf von statischen Methoden
[ BCEL ] Aufruf von statischen Methoden Hinzufügen der Methode zum Constant Pool Sichern der Referenz zur Methode Parameter auf den Stack legen Die Methode mit INVOKESTATIC(Methodenref) aufrufen Rückgabewert liegt nach dem Aufruf auf dem Stack Die folgenden Folien zeigen die verwendeten Schritte im folgenden Beispiel (siehe Beispiel zum besseren Verständnis)

40 Aufruf von nicht-statischen Methoden
[ BCEL ] Aufruf von nicht-statischen Methoden Hinzufügen der Methode zum Constant Pool Sichern der Referenz zur Methode Referenz des Methodenobjektes auf den Stack legen Parameter auf den Stack legen Die Methode mit INVOKEVIRUTAL(Methodenref) aufrufen Rückgabewert liegt nach dem Aufruf auf dem Stack (IM BEISPIEL ERKLÄREN) Hints: Methodenobjekt kann auf verschiedensten Wegen auf den Stack gelegt werden - GETSTATIC (in diesem Fall Hinzufügen des Methodenobjektes zum ConstantPool und sichern dieser Referenz) - GETFIELD - INVOKESTATIC - INVOKEVIRTUAL …

41 Einfügen der Methodenaufrufe
[ BCEL ] Einfügen der Methodenaufrufe Gewünschte Methode finden Generator Objekt davon erstellen Codestelle innerhalb der Methode zum Einfügen finden Gewünschte Aufrufe einfügen Hier soll zusätzlicher Code (in diesem Fall Methodenaufrufe) in eine bestehende Methode eingefügt werden. Finden der Stelle Anfang, Mitte, Ende (wie genau siehe Beispiel)

42 Beispiel Einfügen von „Hello from „ + Methodensignatur
[ BCEL ] Beispiel Einfügen von „Hello from „ + Methodensignatur beim Aufruf jeder Methode einer Klasse (nach Compile Time) Einfügen von Tracing und Logging Informationen beim Aufruf und Verlassen jeder Methode einer Klasse (zur Loading Time) CompileTime  die modifizierten Klassen werden zurückgeschrieben und können danach normal ausgeführt werden. LoadingTime  Klassen werden beim Laden durch Classloader modifiziert, Class Dateien werden NICHT verändert

43 Weitere Frameworks BCEL Jikes Bytecode Toolkit (JikesBT) Javassist
Ermöglicht abstraktere Bytecode Manipulation über Method.append("System.out.println(\"Test\");"); BCEL: schon erwähnt  sehr mächtig aber komplex (Es gibt allerdings auch abstraktere Methoden; so wie wir es gemacht haben ist es aber zum Verständnis von Bytecode besser) JikesBT von IBM ähnlich wie BCEL (demnach auch komplex) Javassist: abstrahiert Bytecodemanipulation, so dass man nachträglich direkt Javacode einfügen kann Man kann also sagen append(„System.out.ptintln(„Test“)); und Javassist kümmert sich um die Umsetzung als Bytecode (also alles das was wir mit BCEL von hand gemacht haben)  Einfacher (da direkt Javacode eingefügt werden kann) aber dadurch nicht so mächtig

44 [ Fazit ] Fazit Bytecodemanipulation ermöglicht die Erweiterung, Optimierung und Anpassung von Classfiles Es ersetzt jedoch nicht das herkömmliche Programmieren in Java, da die Komplexität bedeutend höher ist (1) ..nicht nur bei klassen bei denen der SourceCode nicht zu Verfügung steht (2)

45 [ Quellen ] Quellen (1) Analysis Of The Java Class File (Denis N. Antonioli, Markus Pilz) ftp://ftp.ifi.unizh.ch/pub/techreports/TR-98/ifi ps.gz The JavaTM Virtual Machine Specification Second Edition (Tim Lindholm, Frank Yellin) Inside the Java 2 Virtual Machine (Bill Venners) + Applets

46 [ Quellen ] Quellen (2) Java Programming Dynamics (Dennis M. Sosnoski) BCEL Homepage Beispiele für BCEL Javassist Homepage JikesBT Homepage

47 Fragen zum Thema?

48 Kontakt Ronald Kutschke rk10@hdm-stuttgart.de Daniel Haag
Mirko Bleyh Markus Block


Herunterladen ppt "Bytecodemanipulation"

Ähnliche Präsentationen


Google-Anzeigen