Bytecodemanipulation

Werbung
Bytecodemanipulation
Bytecodemanipulation
Vortrag im Rahmen des Seminars
Generatives Computing
16.06.2004
Ronald Kutschke
Daniel Haag
Mirko Bleyh
Markus Block
1
Bytecodemanipulation
[ Einleitung ]
Übersicht
•
•
•
•
•
•
•
•
•
Motivation
Classfile Format
Java Virtual Machine
Möglichkeiten
Vor- / Nachteile
Beispiel: Framework BCEL
Weitere Anwendungsgebiete
Fazit
Quellen
2
Bytecodemanipulation
[ Einleitung ]
Motivation
Warum Bytecodemanipulation?
•
•
Kein Sourcecode vorhanden
Änderung am Bytecode einfacher, als am Sourcecode
3
Bytecodemanipulation
[ Classfile Format ]
Classfile Format
Public class Person{}
Person.java
Person.class
Person.java
Person.class
Public class Person{
class Adresse{}
}
Person$Adresse.class
4
Bytecodemanipulation
[ Classfile Format ]
Aufbau
CLASSFILE
magic_number
4
version_numbers
4
constant_pool_count
2
constant_pool
n
access_flags
2
this_class
2
super_class
2
interfaces_count
2
interfaces
n
fields_count
2
fields
n
methods_count
2
methods
n
attributes_count
2
attributes
n
5
Bytecodemanipulation
[ Classfile Format ]
Beispiel (1)
public class HelloWorld {
public static void main(String[] args) {
System.out.println("HELLO WORLD");
}
}
“javac HelloWorld.java“
HelloWorld.java
HelloWorld.class
6
Bytecodemanipulation
[ Classfile Format ]
Beispiel (2)
7
Bytecodemanipulation
[ Classfile Format ]
Beispiel (3)
8
Bytecodemanipulation
[ Classfile Format ]
Constantpool (1)
Constantpooleintrag
Typ Angabe
1
Typ spezifisch
n
Constantpool Typ
UTF8 String
01
Class
07
Methodref
0A
NameAndType
0C
...
9
Bytecodemanipulation
[ Classfile Format ]
Constantpool (2)
10
Bytecodemanipulation
[ Classfile Format ]
Constantpool (3)
11
Bytecodemanipulation
[ Classfile Format ]
Inhalt Constantpool
1: UTF8: HelloWorld
2: CLASS: name=#1
3: UTF8: java/lang/Object
4: CLASS: name=#3
5: UTF8: <init>
6: UTF8: ()V
7: UTF8: Code
8: NAMEANDTYPE: name=#5, descriptor=#6
9: METHODREF: class=#4, nameAndType=#8
10: UTF8: LineNumberTable
11: UTF8: LocalVariableTable
12: UTF8: this
13: UTF8: LHelloWorld;
14: UTF8: main
15: UTF8: ([Ljava/lang/String;)V
16: UTF8: java/lang/System
17: CLASS: name=#16
18: UTF8: out
19: UTF8: Ljava/io/PrintStream;
20: NAMEANDTYPE: name=#18, descriptor=#19
21: FIELDREF: class=#17, nameAndType=#20
22: UTF8: HELLO WORLD
23: STRING: string=#22
24: UTF8: java/io/PrintStream
25: CLASS: name=#24
26: UTF8: println
27: UTF8: (Ljava/lang/String;)V
28: NAMEANDTYPE: name=#26, descriptor=#27
29: METHODREF: class=#25, nameAndType=#28
30: UTF8: args
31: UTF8: [Ljava/lang/String;
32: UTF8: SourceFile
33: 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 array
dimension
12
Bytecodemanipulation
[ Classfile Format ]
Methodendefinition
[#24/UTF8] java/io/PrintStream
[#25/Class] name=#24
[#26/UTF8] println
[#27/UTF8] (Ljava/lang/String;)V
[#28/NameAndType] name=#26, desc=#27
[#29/Methodref] class=25 nameAndType=#28
13
Bytecodemanipulation
[ Classfile Format ]
Security
class Login{
private String passwort = “xyz“;
...
public void login(String eingabe){
if(passwort.equals(eingabe)) {
//login durchführen
}
}
...
}
14
Bytecodemanipulation
[ Classfile Format ]
Optimierung (1)
15
Bytecodemanipulation
[ Classfile Format ]
Optimierung (2)
Constantpool: 62%
Methods: 33%
1%
2%
33%
2%
62%
header
class
constant
field
method
Analysis of the Java class file
Denis N. Antoniolli, Markus Pilz
16
Bytecodemanipulation
[ 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
17
Bytecodemanipulation
[ JVM ]
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)
18
Bytecodemanipulation
[ JVM ]
JVM-Architektur
19
Bytecodemanipulation
[ 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
20
Bytecodemanipulation
[ 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
21
Bytecodemanipulation
[ Class Loader ]
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
22
Bytecodemanipulation
[ 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);
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;
}
}
23
Bytecodemanipulation
[ 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
24
Bytecodemanipulation
[ JVM ]
JVM-Architektur
25
Bytecodemanipulation
[ 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
26
Bytecodemanipulation
[ 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
27
Bytecodemanipulation
[ 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 !
28
Bytecodemanipulation
[ 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...
29
Bytecodemanipulation
[ JVM ]
JVM-Architektur
30
Bytecodemanipulation
[ 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
31
Bytecodemanipulation
[ 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
80 - 90 % der CPU Zeit → 10 - 20 % des Codes
wird z.B. in Suns HotSpot VM verwendet
32
Bytecodemanipulation
[ JVM ]
Funktionsweise der JVM
Applet Demo...
33
Bytecodemanipulation
[ Möglichkeiten ]
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
34
Bytecodemanipulation
[ 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
35
Bytecodemanipulation
[ 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
36
Bytecodemanipulation
[ BCEL ]
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
37
Bytecodemanipulation
[ BCEL ]
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
38
Bytecodemanipulation
[ 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
39
Bytecodemanipulation
[ 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
40
Bytecodemanipulation
[ 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
41
Bytecodemanipulation
[ 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)
42
Bytecodemanipulation
[ Frameworks ]
Weitere Frameworks
• BCEL
• Jikes Bytecode Toolkit (JikesBT)
• Javassist
– Ermöglicht abstraktere Bytecode Manipulation über
Method.append("System.out.println(\"Test\");");
43
Bytecodemanipulation
[ 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
44
Bytecodemanipulation
[ Quellen ]
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) + Applets
http://www.artima.com/insidejvm/applets
http://www.artima.com/insidejvm/ed2/jvm.html
45
Bytecodemanipulation
[ Quellen ]
Quellen (2)
•
Java Programming Dynamics (Dennis M. Sosnoski)
http://www-106.ibm.com/developerworks/java/library/j-dyn0429
•
BCEL Homepage
http://jakarta.apache.org/bcel
•
Beispiele für BCEL
http://bcel.sourceforge.net
•
Javassist Homepage
http://www.jboss.org/developers/projects/javassist.html
•
JikesBT Homepage
http://www.alphaworks.ibm.com/tech/jikesbt
46
Bytecodemanipulation
Fragen zum Thema?
47
Bytecodemanipulation
Kontakt
• Ronald Kutschke
[email protected]
• Daniel Haag
[email protected]
• Mirko Bleyh
[email protected]
• Markus Block
[email protected]
48
Herunterladen