Übungen zur Vorlesung Systemarchitektur und

Werbung
Übungen zur Vorlesung Systemarchitektur und -Software
WS 2002/2003
Forschungsgruppe Systemarchitektur und –Software
Ausgabe: 02.12.02 Abgabe: 06.01.03
Dr. R. Riedl
Silvio Meier
Übung 3 (Java Stack, Class-File-Struktur, Java Instruktionssatz)
Informationen zum Java Instruktionssatz finden Sie in der zur Vorlesung empfohlenen
Literatur oder auf der Sun-Web-Seite:
http://java.sun.com/docs/books/vmspec/html/Instructions.doc.html
Aufgabe 1 (Java Stack) [7 Punkte + 1 Bonus-Punkt]
a. Erklären Sie kurz wozu der Java Stack benötigt wird, wie er aufgebaut ist, und wie der
Java Stack in Beziehung mit Threads steht. Beantworten Sie zudem, wie die einzelnen
Datentypen auf dem Java-Stack dargestellt werden. [2 Punkte]
b. Folgender Code sei gegeben:
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
26
public class JavaStackTest {
public static void main(String[] args){
Computation c = new Computation(42);
System.out.println(c.sophisticatedComputation(33));
}
}
class Computation {
private int seed;
public Computation(int seed) {
this.seed = seed;
}
public long sophisticatedComputation(int var) {
int a = var;
int b = var * 2;
int c = var * 3;
return specialSum(a,b,c);
}
public long specialSum(int a, int b, int c){
int swap;
long result = 0;
swap = a; a = c; c = swap;
result = a + b * b + c * c * c + seed;
seed = (int)(result / 2);
return result;
}
}
Berechnen Sie für die beiden oben stehenden Methoden sophisticatedComputation
und specialSum jeweils, wie viel Platz maximal auf dem Java Stack benötigt wird (für
die lokalen Variablen sowie für den Operanden-Stack). [2 Punkte]
c. Zeichnen Sie den Java Stack schematisch auf, unter der Annahme, dass sich obiges
Programm vor Zeile 22 aber nach Zeile 21 in der Ausführung befindet. Zeigen Sie,
was sich je im Bereich der lokalen Variablen und dem Operanden-Stack befindet.
Erläutern Sie. [3 Punkte]
d. Was passiert auf dem Java-Stack genau, wenn in einer Methode eine Exception
geworfen und diese nicht abgefangen wird? Zeigen Sie dies anhand eines konkreten
Beispiels [1 Bonus-Punkt].
Aufgabe 2 – (Java Instruktionssatz – Grundlagen) [8 Punkte]
a. Folgender disassemblierter (in mnemonischer Form) Bytecode einer Java-Methode ist
gegeben:
0 iload_1
1 iload_0
15 goto 26
18 iload_1
2
5
6
7
8
9
10
11
12
13
14
if_icmple 11
iload_1
istore_2
iload_0
istore_1
iload_2
istore_0
iload_0
iload_1
irem
istore_3
19
20
21
22
23
24
25
26
27
30
31
istore_0
iload_3
istore_1
iload_0
iload_1
irem
istore_3
iload_3
ifne 18
iload_1
ireturn
Rekonstruieren Sie die ursprüngliche Java-Methode von Hand und beschreiben Sie,
was diese Methode macht. Wie viele lokale Variablen verwendet diese Methode, von
welchem Typ sind diese lokalen Variablen? Ist die Methode eine Klassen- oder
Instanzmethode? [5 Punkte]
b. Folgende (Instanz-)Methode ist in Java gegeben:
public int integerMultiply(int factor1, int factor2){
int result = 0;
for (int i=0; i < factor1; i++){
result = result + factor2;
}
return result;
}
Diese Methode multipliziert zwei Integer-Zahlen. Übersetzen Sie diese Methode in
Java Bytecode. Sie können anstelle von konkreten Offsets im Bytecode auch
symbolische Sprungmarken (Labels) verwenden. [3 Punkte]
Aufgabe 3 (Java-Class-Files) [4 Punkte]
Auf dem Markt sind sogenannte Decompiler verfügbar, mit denen (kompilierte) JavaClassfiles wieder dekompiliert, d.h. wieder in Source Code umgewandelt werden können. Für
interessierte Studierende: Ein sehr guter, frei verfügbarer Decompiler ist z.B. unter
http://kpdus.tripod.com/jad.html zu finden.
a. Versuchen Sie anhand der Java-Class-File-Struktur herauszufinden warum
kompilierter Java Code wieder dekompiliert werden kann. Nennen Sie mehrere
Gründe warum dies so ist. [2 Punkte]
b. Was könnte man machen, damit Java-Class-Files nicht mehr so einfach
dekompilierbar sind? [2 Punkte]
Aufgabe 4 (Methodenaufrufe) [5 Punkte]
Polymorphie ist ein wichtiges Konzept in der objektorientierten Softwareentwicklung. U.a.
wird dieses Konzept durch sogenanntes dynamisches Binden unterstützt. Gegeben sei
folgender Java-Code:
1 public class DynamicBinding {
2
public static void main(String[] args) {
3
Base b = new InheritedClass();
4
b.methodCaller();
5
}
6 }
7 class Base {
8
public Base() {
9
}
10
public void publicMethod() {
11
System.out.println("super class public method");
12
}
13
protected void protectedMethod() {
14
System.out.println("super class protected method");
15
}
16
private void privateMethod() {
17
System.out.println("super class private method");
18
}
19
public void methodCaller()
20
{
21
publicMethod();
22
//
0
0:aload_0
23
//
1
1:invokevirtual
#7
<Method void publicMethod()>
24
protectedMethod();
25
//
2
4:aload_0
26
//
3
5:invokevirtual
#8
<Method void protectedMethod()>
27
privateMethod();
28
//
4
8:aload_0
29
//
5
9:invokespecial
#9
<Method void privateMethod()>
30
//
6
12:return
31
}
32 }
33 class InheritedClass extends Base {
34
public void publicMethod() {
35
System.out.println("sub class public method");
36
}
37
protected void protectedMethod() {
38
System.out.println("sub class protected method");
39
}
40
private void privateMethod() {
41
System.out.println("sub class private method");
42
}
42 }
Wird das Programm durch das Ausführen der Klasse DynamicBinding gestartet, so wird
folgendes ausgegeben:
sub class public method
sub class protected method
super class private method
a. Was für Operanden liegen auf dem Operanden-Stack unmittelbar vor der Ausführung
der Methode publicMehtod(). Sie müssen keine konkreten Werte nennen, sondern nur
die Typen der Daten und wieviele Bytes diese belegen. Beschreiben Sie kurz für
welchen Zweck diese Operanden für den Methodenaufruf benötigt werden. [1 Punkt]
b. Versuchen Sie anhand der resultierenden Ausgabe die unterschiedliche
Funktionsweise der Bytecodeinstruktion invokespecial und invokevirtual zu
beschreiben. Dazu finden Sie in der Methode methodCaller() die
Bytecodeinstruktionen als Kommentar zu jedem Methodenaufzuf zugeordnet. [3
Punkte]
c. Beschreiben Sie ganz kurz was bei der Instruktion return bzw. areturn, ireturn,
dreturn, freturn und lreturn passiert. [1 Punkt]
Aufgabe 5 (Switch-Statement) [6 Punkte]
a. Erklären Sie ganz kurz den Unterschied zwischen lookupswitch und tableswitch
Instruktion. [1 Punkt]
b. Folgende Methode sei gegeben:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args) {
int a = 3;
int b = 0;
switch (a) {
case 1:
b = b * a;
break;
case 5:
b = b * 3;
break;
default:
b = 0;
}
int c;
switch (b) {
case 4:
c = 3;
break;
case 5:
21
22
21
23
24
23
24
25
}
26 }
c = 2 * b;
break;
case 6:
c = 7;
break;
default:
c = 0;
Übersetzen Sie diese Java-Methode in mnemonischen Bytecode. Sie können dabei anstelle
von konkreten Offsets symbolische Sprungmarken verwenden (labels). Orientieren Sie
sich an den Beispielen auf den Vorlesungsfolien 70 und 71. [4 Punkte]
c. Gegeben sei folgendes Java-Codefragment:
char d;
int b;
...
switch (b) {
case 4:
d = 'A';
case 5:
d = 'B';
default:
d = 'C';
}
Dieser Code wird durch einen Java Compiler wie folgt in Bytecode übersetzt:
79 iload_2
80 lookupswitch 2: default=116
4: 108
5: 112
108 bipush 65
110 istore 4
112 bipush 66
114 istore 4
116 bipush 67
117 istore 4
Inwiefern entspricht diese Übersetzung nicht Ihren Erwartungen? Haben Sie eine
Erklärung warum das oben stehende Codefragment so übersetzt wird? Versuchen Sie mit
Hilfe der Informationen, die Sie in der angegebenen Literatur finden, eine Erklärung zu
finden. [1 Punkt]
Herunterladen