eclipse-jdt / eclipse-jdt/eclipse.jdt.core

ECJ generates invalid bytecode with VerifyError for nested try-finally blocks

Open
#4,126 3 comments 0 reactions 1 assignee Claimed by @srikanth-sankaran View on GitHub
Dominant language
Java
Stars
237
Forks
195
Avg merge
1d 12h
Merged PRs (30d)
47

Description

Environment:
ECJ Version:
```
Eclipse Compiler for Java(TM) v20250613-1403, 3.42.50, Copyright IBM Corp 2000, 2020. All rights reserved
```
Java Version:

```
java version "1.8.0_451"
Java(TM) SE Runtime Environment (build 1.8.0_451-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.451-b10, mixed mode)

java version "11.0.27" 2025-04-15 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.27+8-LTS-232)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.27+8-LTS-232, mixed mode)

java version "17.0.15" 2025-04-15 LTS
Java(TM) SE Runtime Environment (build 17.0.15+9-LTS-241)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.15+9-LTS-241, mixed mode, sharing)

java version "21.0.7" 2025-04-15 LTS
Java(TM) SE Runtime Environment (build 21.0.7+8-LTS-245)
Java HotSpot(TM) 64-Bit Server VM (build 21.0.7+8-LTS-245, mixed mode, sharing)
```
Javac Version:

```
javac 1.8.0_451
javac 11.0.27
javac 17.0.15
javac 21.0.7
```

Description:
We have identified a test program compiled by javac and ECJ with different runtime behavior. This happens in JDK 8, 11, 17, and 21.

The program compiled by javac will execute successfully.
However, the program compiled by ECJ will throw `java.lang.VerifyError`.

Test program:
```java
public class Test {
public static void main(String[] args) {
int index = 0;
while (index > 0) {
try {
try {
int result = 42;
return;
} finally {
try {
int result = 42;
return;
} finally {
System.out.println(42);
}
}
} catch (Exception e) {
System.out.println("Caught Exception");
}
}
}
}

```

When running the program compiled by javac, it will execute successfully.
```bash
javac Test.java
java Test
```

However, when compiling the same program using ECJ and running it, the program will throw `java.lang.VerifyError`.

```bash
java -jar ecj-4.36M3.jar --release 21 -d . Test.java
java Test
Error: Unable to initialize main class Test
Caused by: java.lang.VerifyError: Instruction type does not match stack map
Exception Details:
Location:
Test.main([Ljava/lang/String;)V @24: ifgt
Reason:
Current frame's stack size doesn't match stackmap.
Current Frame:
bci: @24
flags: { }
locals: { '[Ljava/lang/String;', integer }
stack: { integer }
Stackmap Frame:
bci: @24
flags: { }
locals: { '[Ljava/lang/String;', integer }
stack: { }
Bytecode:
0000000: 033c a700 15b2 000d 102a b600 13b1 57b2
0000010: 000d 1219 b600 1b1b 9d00 00b1
Exception Handler Table:
bci [5, 13] => handler: 14
Stackmap Table:
append_frame(@5,Integer)
same_locals_1_stack_item_frame(@14,Object[#30])
same_frame(@23)
same_frame(@24)
```

Expected behavior: Program should execute successfully.
Actual behavior: Program throws `java.lang.VerifyError`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.