Thomas Darimont
Erfahrenes Mitglied
Hallo!
Wer sich schon immer mal anschauen wollte, was euer Java Kompiler (z.Bsp. der von Sun) so aus euren Programmen macht der / (oder die) jenige kann ja mal folgendes Versuchen:
Wir wollen uns den bytecode dieses Java Prorgamms anschauen.
Dazu lassen wir das ganze Kompilieren und begeben uns über eine Shell auf die Suche nach dem erzeugten Classfile.
Wir verwenden nun das kleine Programm javap mit welchem wir das Classfile Disassemblen können. Mittels der Option -private bestimmen wir, dass auch private Methoden disassembliert werden sollen.
Nun geben wir folgenden Befehl ein
hier hab ich mal versucht die beiden Methoden etwas genauer zu Beschreiben:
Erklärungen zu den einzelnen OpCodes findet man z.Bsp. hier:
http://www.tutorials.de/tutorials203705.html
Gruß Tom
Wer sich schon immer mal anschauen wollte, was euer Java Kompiler (z.Bsp. der von Sun) so aus euren Programmen macht der / (oder die) jenige kann ja mal folgendes Versuchen:
Wir wollen uns den bytecode dieses Java Prorgamms anschauen.
Code:
/*
* Created on 04.05.2005@17:03:49 by Darimont
*
* TODO Licence info
*/
package de.tutorials;
/**
* @author Darimont TODO Explain me
*/
public class FooTest {
public static void main(String[] args) {
long time = -System.currentTimeMillis();
methodA();
System.out.println(time + System.currentTimeMillis());
time = -System.currentTimeMillis();
methodB();
System.out.println(time + System.currentTimeMillis());
}
/**
*
*/
private static void methodB() {
int i = 0;
while (i <= 1000000000) {
int foo = i + 5;
i++;
}
}
/**
*
*/
private static void methodA() {
int foo = 0;
int i = 0;
while (i <= 1000000000) {
foo = i + 5;
i++;
}
}
}
Dazu lassen wir das ganze Kompilieren und begeben uns über eine Shell auf die Suche nach dem erzeugten Classfile.
Wir verwenden nun das kleine Programm javap mit welchem wir das Classfile Disassemblen können. Mittels der Option -private bestimmen wir, dass auch private Methoden disassembliert werden sollen.
Nun geben wir folgenden Befehl ein
Code:
E:\eclipse\3.1M6\eclipse\workspace\de.tutorials.training\bin>
javap -c -private de.tutorials.FooTest
Compiled from "FooTest.java"
public class de.tutorials.FooTest extends java.lang.Object{
public de.tutorials.FooTest();
Code:
0: aload_0
1: invokespecial #9; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #21; //Method java/lang/System.currentTimeMillis:()J
3: lneg
4: lstore_1
5: invokestatic #24; //Method methodA:()V
8: getstatic #28; //Field java/lang/System.out:Ljava/io/PrintStream;
11: lload_1
12: invokestatic #21; //Method java/lang/System.currentTimeMillis:()J
15: ladd
16: invokevirtual #34; //Method java/io/PrintStream.println:(J)V
19: invokestatic #21; //Method java/lang/System.currentTimeMillis:()J
22: lneg
23: lstore_1
24: invokestatic #37; //Method methodB:()V
27: getstatic #28; //Field java/lang/System.out:Ljava/io/PrintStream;
30: lload_1
31: invokestatic #21; //Method java/lang/System.currentTimeMillis:()J
34: ladd
35: invokevirtual #34; //Method java/io/PrintStream.println:(J)V
38: return
private static void methodB();
Code:
0: iconst_0
1: istore_0
2: goto 12
5: iload_0
6: iconst_5
7: iadd
8: istore_1
9: iinc 0, 1
12: iload_0
13: ldc #42; //int 1000000000
15: if_icmple 5
18: return
private static void methodA();
Code:
0: iconst_0
1: istore_0
2: iconst_0
3: istore_1
4: goto 14
7: iload_1
8: iconst_5
9: iadd
10: istore_0
11: iinc 1, 1
14: iload_1
15: ldc #42; //int 1000000000
17: if_icmple 7
20: return
}
E:\eclipse\3.1M6\eclipse\workspace\de.tutorials.training\bin>
hier hab ich mal versucht die beiden Methoden etwas genauer zu Beschreiben:
Code:
private static void methodB();
Code:
0: iconst_0 // Lege int mit Wert 0 auf den Stack
1: istore_0 // Nimmt den int vom Stack und speichert ihn in der lokalen Variablen(0)
2: goto 12 //gehe zur Marke 12
5: iload_0 // lege lokale Variable(0) auf den Stack
6: iconst_5 // Lege int mit Wert 5 auf den Stack
7: iadd // Nehme zwei int Werte vom Stack, addiere diese und lege das Ergebnis zurück
8: istore_1 // Nimmt den int vom Stack und speichert ihn in der lokalen Variablen(1)
9: iinc 0, 1 // Inkrementiere die lokale variable(0) um 1
12: iload_0 // lege lokale Variable(0) auf den Stack
13: ldc #42; //int 1000000000 // lege int mit Wert 1000000000 auf den Stack
15: if_icmple 5 // Nimmt die beiden obersten Werte vom Stack und vergleicht diese. Wenn der Wert(0)<=Wert(1) dann springe zur Marke 5
18: return // return. Blockabschluss
------------------------------------------------------
private static void methodA();
Code:
0: iconst_0 // Lege int mit Wert 0 auf den Stack
1: istore_0 // Nimmt den int vom Stack und speichert ihn in der lokalen Variablen(0)
2: iconst_0 // Lege int mit Wert 0 auf den Stack
3: istore_1 // Nimmt den int vom Stack und speichert ihn in der lokalen Variablen(1)
4: goto 14 //Gehe zur Marke 14
7: iload_1 // lege lokale Variable(1) auf den Stack
8: iconst_5 // Lege int mit Wert 5 auf den Stack
9: iadd // Nehme zwei int Werte vom Stack, addiere diese und lege das Ergebnis zurück auf den Stack.
10: istore_0 // Nimmt den int vom Stack und speichert ihn in der lokalen Variablen(0)
11: iinc 1, 1 // Inkrementiere die Lokale Variable(1) um 1
14: iload_1 // lege lokale Variable(1) auf den Stack
15: ldc #42; //int 1000000000 // lege int mit (int) Wert 1000000000 auf den Stack
17: if_icmple 7 //Nimmt die beiden obersten Werte vom Stack und vergleicht diese. Wenn der Wert(0)<=Wert(1) dann springe zur Marke 7
20: return // return. Blockabschluss
Erklärungen zu den einzelnen OpCodes findet man z.Bsp. hier:
http://www.tutorials.de/tutorials203705.html
Gruß Tom