Bytecodemanipulation
1
Bytecodemanipulation
Vortrag im Rahmen des Seminars Generatives Computing
16.06.2004
Ronald KutschkeDaniel HaagMirko Bleyh
Markus Block
Bytecodemanipulation
2
Übersicht
• Motivation• Classfile Format• Java Virtual Machine• Möglichkeiten• Vor- / Nachteile• Beispiel: Framework BCEL• Weitere Anwendungsgebiete• Fazit• Quellen
[ Einleitung ]
Bytecodemanipulation
3
Motivation
Warum Bytecodemanipulation?
• Kein Sourcecode vorhanden• Änderung am Bytecode einfacher, als am Sourcecode
[ Einleitung ]
Bytecodemanipulation
4
Classfile Format
Public class Person{}
Person.java Person.class
Public class Person{class Adresse{}
}
Person.java Person.class
Person$Adresse.class
Public class Person{}
Person.java Person.class
Public class Person{class Adresse{}
}
Person.java Person.class
Person$Adresse.class
[ Classfile Format ]
Bytecodemanipulation
5
Aufbau
magic_number
version_numbers
constant_pool_count
constant_pool
access_flags
this_class
super_class
interfaces_count
CLASSFILE
interfaces
methods_count
methods
attributes_count
fields_count
fields
attributes
4
4
2
n
2
2
2
2
n
2
n
2
2
n
n
[ Classfile Format ]
Bytecodemanipulation
6
Beispiel (1)
HelloWorld.java HelloWorld.class
public class HelloWorld {public static void main(String[] args) {
System.out.println("HELLO WORLD");}
}
“javac HelloWorld.java“
[ Classfile Format ]
Bytecodemanipulation
7
Beispiel (2)
[ Classfile Format ]
Bytecodemanipulation
8
Beispiel (3)
magic_number
version_numbers
constant_pool_count
constant_pool
access_flags
this_class
super_class
interfaces_count
CLASSFILE
interfaces
methods_count
methods
attributes_count
fields_count
fields
attributes
[ Classfile Format ]
Bytecodemanipulation
9
Constantpool (1)
Typ Angabe
Typ spezifisch
Constantpooleintrag
1
n
UTF8 String
Class
Methodref
NameAndType
Constantpool Typ01
07
0A
0C
...
[ Classfile Format ]
Bytecodemanipulation
10
Constantpool (2)
Typ Angabe
Länge
UTF8 String
1
nLänge 2
Inhalt n
01
10
HelloWorld
[ Classfile Format ]
Bytecodemanipulation
11
Constantpool (3)
Typ Angabe
Länge
Class
1
nName Index 2
07
00 01
[ Classfile Format ]
Bytecodemanipulation
12
Inhalt Constantpool1: UTF8: HelloWorld2: CLASS: name=#13: UTF8: java/lang/Object4: CLASS: name=#35: UTF8: <init>6: UTF8: ()V7: UTF8: Code8: NAMEANDTYPE: name=#5, descriptor=#69: METHODREF: class=#4, nameAndType=#810: UTF8: LineNumberTable11: UTF8: LocalVariableTable12: UTF8: this13: UTF8: LHelloWorld;14: UTF8: main15: UTF8: ([Ljava/lang/String;)V16: UTF8: java/lang/System17: CLASS: name=#1618: UTF8: out19: UTF8: Ljava/io/PrintStream;20: NAMEANDTYPE: name=#18, descriptor=#1921: FIELDREF: class=#17, nameAndType=#2022: UTF8: HELLO WORLD23: STRING: string=#2224: UTF8: java/io/PrintStream25: CLASS: name=#2426: UTF8: println27: UTF8: (Ljava/lang/String;)V28: NAMEANDTYPE: name=#26, descriptor=#2729: METHODREF: class=#25, nameAndType=#2830: UTF8: args31: UTF8: [Ljava/lang/String;32: UTF8: SourceFile33: UTF8: HelloWorld.java
BaseType Character
Type Interpretation
B byte signed byte
C char Unicode character
D double double-precision floating-point value
F float single-precision floating-point value
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
[ reference one arraydimension
[ Classfile Format ]
Bytecodemanipulation
13
Methodendefinition
[#26/UTF8] println
[#27/UTF8] (Ljava/lang/String;)V
[#28/NameAndType] name=#26, desc=#27
[#29/Methodref] class=25 nameAndType=#28
[#24/UTF8] java/io/PrintStream
[#25/Class] name=#24
[ Classfile Format ]
Bytecodemanipulation
14
Security
class Login{
private String passwort = “xyz“;
...
public void login(String eingabe){
if(passwort.equals(eingabe)) {
//login durchführen
}
}
...
}
[ Classfile Format ]
Bytecodemanipulation
15
Optimierung (1)
magic_number
version_numbers
constant_pool_count
constant_pool
access_flags
this_class
super_class
interfaces_count
CLASSFILE
interfaces
methods_count
methods
attributes_count
fields_count
fields
attributes
[ Classfile Format ]
Bytecodemanipulation
16
Optimierung (2)
[ Classfile Format ]
62%2%
33%
1% 2%
header
class
constant
field
method
Constantpool: 62%Methods: 33%
Analysis of the Java class fileDenis N. Antoniolli, Markus Pilz
Bytecodemanipulation
17
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
[ JVM ]
Bytecodemanipulation
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)
[ JVM ]
Bytecodemanipulation
19
JVM-Architektur
[ JVM ]
Bytecodemanipulation
20
Motivation
– Speicherort der Klassen kann sehr unterschiedlich sein:• Lokales Dateisystem• Entferntes Dateisystem• Datenbank• Internet
[ Class Loader ]
– Zentraler Punkt zum Laden von Klassen Erhöhte Sicherheit
Bytecodemanipulation
21
Aufgaben
Um eine Klasse verwenden zu können, muss Folgendes von der VM bzw. dem Class Loader erledigt werden:
[ Class Loader ]
– 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
Bytecodemanipulation
22
Bootstrap Class Loader
Problem: Der Class Loader selber ist auch eine Java Klasse! Wer lädt diesen?
[ Class Loader ]
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
Bytecodemanipulation
23
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);if (c != null) return c;
} catch (ClassNotFoundException e) {}try {
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;
}}
[ Class Loader ]
Bytecodemanipulation
24
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
[ Class Loader ]
Bytecodemanipulation
25
JVM-Architektur
[ JVM ]
Bytecodemanipulation
26
• Method Area:– Enthält alle Klassen-Informationen (Name, Superklasse,
Constant Pool, Methoden-Informationen und –Bytecode, Exception-Table, Klassenvariablen, etc.)
– Gehört logisch zum Heap
[ Runtime Data Areas ]
• 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
Bytecodemanipulation
27
• 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
[ Runtime Data Areas ]
• Native Method Stack:– Führt Programm-Code aus, der nicht in Java geschrieben ist– Optional
Bytecodemanipulation
28
• 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 !
[ Runtime Data Areas ]
Bytecodemanipulation
29
• Stack Frame
[ Runtime Data Areas ]
– 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...
Bytecodemanipulation
30
JVM-Architektur
[ JVM ]
Bytecodemanipulation
31
3 unterschiedliche Bedeutungen:
[ Execution Engine ]
– 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
Bytecodemanipulation
32
Implementierungen
• Interpretation– sehr einfach (1. Generation der VMs)
[ Execution Engine ]
• Just-in-Time Kompilierung– 1. Ausführung einer Methode → nativer Code
• Adaptive Optimierung– Mischung aus Interpretation und JIT Kompilierung– Code-Ausführung wird beobachtet– 80 - 90 % der CPU Zeit → 10 - 20 % des Codes– wird z.B. in Suns HotSpot VM verwendet
Bytecodemanipulation
33
Funktionsweise der JVM
Applet Demo...
[ JVM ]
Bytecodemanipulation
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
[ Möglichkeiten ]
Bytecodemanipulation
35
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
[ Vor- / Nachteile ]
Bytecodemanipulation
36
Nachteile
• Aufwändig– Genaue Kenntnis des Classfile-Formats, der Opcodes und
der VM sind Voraussetzung– Fehlen von Kommentaren
• Fehler erscheinen erst zur Laufzeit
[ Vor- / Nachteile ]
Bytecodemanipulation
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 ]
Bytecodemanipulation
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
[ BCEL ]
Bytecodemanipulation
39
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
[ BCEL ]
Bytecodemanipulation
40
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
[ BCEL ]
Bytecodemanipulation
41
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
[ BCEL ]
Bytecodemanipulation
42
Beispiel
• Einfügen von „Hello from „ + Methodensignaturbeim 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)
[ BCEL ]
Bytecodemanipulation
43
Weitere Frameworks
• BCEL• Jikes Bytecode Toolkit (JikesBT)• Javassist
– Ermöglicht abstraktere Bytecode Manipulation über Method.append("System.out.println(\"Test\");");
[ Frameworks ]
Bytecodemanipulation
44
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
[ Fazit ]
Bytecodemanipulation
45
Quellen (1)
• Analysis Of The Java Class File (Denis N. Antonioli, Markus Pilz)ftp://ftp.ifi.unizh.ch/pub/techreports/TR-98/ifi-98.04.ps.gz
• The JavaTM Virtual Machine Specification Second Edition(Tim Lindholm, Frank Yellin)http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html
• Inside the Java 2 Virtual Machine (Bill Venners) + Appletshttp://www.artima.com/insidejvm/appletshttp://www.artima.com/insidejvm/ed2/jvm.html
[ Quellen ]
Bytecodemanipulation
46
Quellen (2)
• Java Programming Dynamics (Dennis M. Sosnoski)http://www-106.ibm.com/developerworks/java/library/j-dyn0429
• BCEL Homepagehttp://jakarta.apache.org/bcel
• Beispiele für BCELhttp://bcel.sourceforge.net
• Javassist Homepagehttp://www.jboss.org/developers/projects/javassist.html
• JikesBT Homepagehttp://www.alphaworks.ibm.com/tech/jikesbt
[ Quellen ]
Bytecodemanipulation
47
Fragen zum Thema?
Bytecodemanipulation
48
Kontakt
• Ronald Kutschke [email protected]
• Daniel [email protected]
• Mirko [email protected]
• Markus [email protected]