Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 71875f4

Browse files
committed
Correct the order of constructor and static initialization
In `new` opcode, jvm needs to call constructor and initialization in order. The sequence is begin at base class static initialization, and then derived class static initialization. After all classes are initialized, base class constructor will be executed, then execute its child class constructor. Add a new test script: Initializer.java
1 parent dd4ca90 commit 71875f4

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

‎Makefile‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ TESTS = \
4949
Field \
5050
Static \
5151
Invokevirtual \
52-
Inherit
52+
Inherit \
53+
Initializer
5354

5455
check: $(addprefix tests/,$(TESTS:=-result.out))
5556

‎jvm.c‎

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,8 +1196,26 @@ stack_entry_t *execute(method_t *method,
11961196

11971197
char *class_name = find_class_name_from_index(index, clazz);
11981198
class_file_t *target_class;
1199-
if (find_or_add_class_to_heap(class_name, prefix, &target_class)) {
1200-
/* Call static initialization */
1199+
1200+
/* FIXME: use linked list to prevent wasted space */
1201+
class_file_t **stack = malloc(sizeof(class_file_t *) * 100);
1202+
size_t count = 0;
1203+
while (true) {
1204+
find_or_add_class_to_heap(class_name, prefix, &target_class);
1205+
assert(target_class && "Failed to load class in i_new");
1206+
stack[count++] = target_class;
1207+
class_name = find_class_name_from_index(
1208+
target_class->info->super_class, target_class);
1209+
if (!strcmp(class_name, "java/lang/Object"))
1210+
break;
1211+
}
1212+
1213+
/* call static initialization */
1214+
while (count) {
1215+
target_class = stack[--count];
1216+
if (target_class->initialized)
1217+
continue;
1218+
target_class->initialized = true;
12011219
method_t *method = find_method("<clinit>", "()V", target_class);
12021220
if (method) {
12031221
local_variable_t own_locals[method->code.max_locals];
@@ -1208,7 +1226,7 @@ stack_entry_t *execute(method_t *method,
12081226
free(exec_res);
12091227
}
12101228
}
1211-
assert(target_class&&"Failed to load class in new");
1229+
free(stack);
12121230

12131231
object_t *object = create_object(target_class);
12141232
push_ref(op_stack, object);

‎tests/Initializer.java‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
public class Initializer {
2+
static {
3+
System.out.println(1);
4+
}
5+
Initializer () {
6+
System.out.println(2);
7+
}
8+
public static void call() {
9+
10+
}
11+
public static void main(String[] args) {
12+
/* only call `Initializer` init */
13+
InitializerB.call();
14+
/* call remaining init in order */
15+
InitializerB obj = new InitializerB();
16+
}
17+
}
18+
19+
class InitializerA extends Initializer {
20+
static {
21+
System.out.println(3);
22+
}
23+
InitializerA() {
24+
super();
25+
System.out.println(4);
26+
}
27+
}
28+
29+
class InitializerB extends InitializerA {
30+
static {
31+
System.out.println(5);
32+
}
33+
InitializerB() {
34+
super();
35+
System.out.println(6);
36+
}
37+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /