Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler Bug with Record Pattern (java.lang.VerifyError: Stack map does not match the one at exception handler) #3479

Closed
musiKk opened this issue Jan 28, 2024 · 14 comments
Labels

Comments

@musiKk
Copy link

musiKk commented Jan 28, 2024

I randomly started encountering the following error in one of my projects and am unable to get rid of it

Error: Unable to initialize main class com.github.musiKk.Runner
Caused by: java.lang.VerifyError: Stack map does not match the one at exception handler 147

Even though the bug surfaces during running/debugging, I strongly believe that the error occurs during compilation. I know that reports of compiler bugs are often met with scepticism but I verified that it works with the OpenJDK compiler (Temurin) and reliably and repeatedly fails when compiling with VSCode.

Environment
  • Operating System: MacOS Sonoma 14.1.2
  • JDK version: Temurin-21.0.2+13 (build 21.0.2+13-LTS)
  • Visual Studio Code version: 1.85.2
  • Java extension version: 1.26.0
Steps To Reproduce
  1. check out my project at this commit; I have not been able to isolate the issue into a smaller project so far (also see below)
  2. open the project in VSCode
  3. open the class "com.github.musiKk.Runner"
  4. run the main method with one of the following methods (the code is safe to run, it only reads one file included in the repository, it also has zero dependencies)
    1. click "run" or "debug"
    2. run via CLI from the project's root with java -cp target/classes com.github.musiKk.Runner

I tried the following workarounds, none of them worked:

  • older and prerelease versions of the VSCode Java plugin
  • copy the class into a new file
  • delete the language server workspace
  • check the project out into a different directory and start from scratch
  • disable Lombok just in case

I had a look at the language server log file but it only contained tons of occurrences of the following error which I'm not sure is related:

Java Model Exception: Error in Java Model (code 1006): <module:java.xml> is not on its project's build path
Current Result

The following error occurs:

Error: Unable to initialize main class com.github.musiKk.Runner
Caused by: java.lang.VerifyError: Stack map does not match the one at exception handler 133
Exception Details:
  Location:
    com/github/musiKk/Runner.execute(Lcom/github/musiKk/Statement;Lcom/github/musiKk/Runner$StackFrame;)Lcom/github/musiKk/Runner$Value; @133: astore
  Reason:
    Type 'com/github/musiKk/Statement' (current frame, locals[1]) is not assignable to 'com/github/musiKk/Runner$StackFrame' (stack map, locals[1])
  Current Frame:
    bci: @18
    flags: { }
    locals: { 'com/github/musiKk/Runner', 'com/github/musiKk/Statement', 'com/github/musiKk/Runner$StackFrame', 'com/github/musiKk/Statement', top, 'com/github/musiKk/Statement' }
    stack: { 'java/lang/Throwable' }
  Stackmap Frame:
    bci: @133
    flags: { }
    locals: { 'com/github/musiKk/Runner', 'com/github/musiKk/Runner$StackFrame' }
    stack: { 'java/lang/Throwable' }
  Bytecode:
    0000000: 2b3a 0519 05c1 0098 9900 2219 054e 2dc0
    0000010: 0098 b601 4f3a 0419 05c0 0098 1905 c000
    0000020: 9858 2a19 042c b601 0eb0 2b3a 0719 07c1
    0000030: 0151 9900 4219 07c0 0151 593a 0619 07c0
    0000040: 0151 5819 06b6 0153 2a2c ba01 5600 00b6
    0000050: 00d8 3a08 2c19 06b6 0157 bb00 4659 1906
    0000060: b601 5719 0801 b600 e9c0 00ec b701 13b6
    0000070: 0116 01b0 bb01 0159 2bb8 012b ba01 5800
    0000080: 00b7 0105 bf3a 08bb 0159 5919 08b6 015b
    0000090: 1908 b701 60bf
  Exception Handler Table:
    bci [18, 21] => handler: 133
  Stackmap Table:
    same_frame(@42)
    same_frame_extended(@116)
    full_frame(@133,{Object[#1],Object[#41]},{Object[#348]})

It looks like the error is triggered in this method:

    private Value execute(Statement expression, StackFrame frame) {
        return switch (expression) {
            case ExpressionStatement(Expression e) -> evaluateExpression(e, frame);
            case VariableDeclaration vds -> {
                var optValue = vds.initializer().map(initializer -> evaluateExpression(initializer, frame));
                frame.putVariable(vds.name(), new Variable(vds.name(), optValue.orElse(null)));
                yield null;
            }
            default -> throw new RuntimeException("not yet implemented " + expression);
        };
    }

It looks like there may be a very special problem with matching the structure of the records (the first case). If I refactor the switch to

if (expression instanceof ExpressionStatement(Expression e)) ->

it still fails. If I refactor to

if (expression instanceof ExpressionStatement es) ->

it succeeds.

That being said, I tried to isolate the issue with this test but here the error does not happen.

Expected Result

The code runs.

Additional Informations

It is important that the class was compiled by VSCode/the embedded Eclipse compiler! When compiling this on the command line with mvn clean compile which delegates to the installed JDK, the code works (ignore any exceptions that occur, the code is not correct but that is not the point). Then, it also does not matter which method from step 4 is used; it always succeeds. As soon as the file is touched from within VSCode and compilation is triggered, the VerifyError is back.

@snjeza
Copy link
Contributor

snjeza commented Jan 31, 2024

This is an upstream jdt.core issue - eclipse-jdt/eclipse.jdt.core#1796
eclipse-jdt/eclipse.jdt.core#1823 will fix it.

@musiKk
Copy link
Author

musiKk commented Feb 1, 2024

Thanks! Do you want this issue closed or should we wait until upstream has a fix?

@snjeza
Copy link
Contributor

snjeza commented Feb 1, 2024

We will wait. eclipse-jdt/eclipse.jdt.core#1796 is not merged yet

@snjeza
Copy link
Contributor

snjeza commented Mar 4, 2024

eclipse-jdt/eclipse.jdt.core#1796 has been merged.

@snjeza snjeza closed this as completed Mar 4, 2024
@musiKk
Copy link
Author

musiKk commented Mar 10, 2024

It's not fixed, the bug is still present in the extension. Both release and pre-release.

@snjeza
Copy link
Contributor

snjeza commented Mar 10, 2024

I can't reproduce the issue.
I get the following output with javac or ecj (VS Code embedded):

hello world
Exception in thread "main" java.lang.RuntimeException: symbol x not found
	at com.github.musiKk.Runner$DefaultScope.getVariable(Runner.java:210)
	at com.github.musiKk.Runner$DefaultScope.getVariable(Runner.java:208)
	at com.github.musiKk.Runner$StackFrame.getVariable(Runner.java:269)
	at com.github.musiKk.Runner.evaluateExpression(Runner.java:68)
	at com.github.musiKk.Runner.evaluateExpression(Runner.java:88)
	at com.github.musiKk.Runner.execute(Runner.java:118)
	at com.github.musiKk.Runner.evaluateExpression(Runner.java:107)
	at com.github.musiKk.Runner.execute(Runner.java:118)
	at com.github.musiKk.Runner.execute(Runner.java:47)
	at com.github.musiKk.Runner.execute(Runner.java:52)
	at com.github.musiKk.Runner.main(Runner.java:31)

Could you try to the following:

- exit VS Code
- rm -rf .classpath .project .settings/ target/
- code .

@musiKk
Copy link
Author

musiKk commented Mar 11, 2024

Interesting, I used the reproducer from the issue you linked. For me that one consistently fails with a VerifyError in VS Code but succeeds when compiled with OpenJDK. I'm at v1.28.1 of the Language Support extension (redhat.java).

@snjeza
Copy link
Contributor

snjeza commented Mar 11, 2024

@musiKk The issue is reproducible in v1.28.1. Could you, please, try pre-release?

@musiKk
Copy link
Author

musiKk commented Mar 12, 2024

I tested with v1.29.2024030708 (pre-release) and it works. Thank you for the support!

edit: I noticed that I stated earlier that I already tried pre-release. I was so sure that I recompiled after switching versions but it seems I messed it up. Apologies for the noise!

@fbricon fbricon added this to the Mid March 2024 milestone Mar 12, 2024
@fbricon fbricon added the bug label Mar 12, 2024
@Nightenom
Copy link

Nightenom commented Mar 13, 2024

Sorry for issue hijacking, but i can still reproduce in my code: https://gist.github.com/Nightenom/b857fb93a41f7e8bcbb69b103476395c#file-crash
(i can't share whole project right now, so made almost compilable snippet)

Using v1.29.2024031308 (pre-release), did "force java compilation: full" and "clean java language server workspace" yet no success, gradle clean/cleanEclipse didn't help either
Project is simple gradle java setup without any hacky things
Meanwhile i'm using debug through jar, which is a bit slower but at least it works

@snjeza
Copy link
Contributor

snjeza commented Mar 13, 2024

(i can't share whole project right now, so made almost compilable snippet)

@musiKk could you create a project example?

@musiKk
Copy link
Author

musiKk commented Mar 14, 2024

I'm not the author of the comment. @Nightenom can you fulfill the request?

@Nightenom
Copy link

I thought he meant me too

could you create a project example?

@snjeza not right now, tight schedule, but since i have a half-way workaround through jar debug it can wait

@Caceresenzo
Copy link

Upgrading Eclipse works.

For those that still want a minimal reproducible example:

public class Hello {

	public static void main(String[] args) {}

	class Group {}

	enum Tag {
		A
	};

	sealed interface ContentSource {

		public static record MultipartSource(
			Object multipart
		) implements ContentSource {}

		public static record FileSource(
			Object file
		) implements ContentSource {}

	}

	public Object uploadFile(Group group, Tag tag, ContentSource file) {
		return switch (file) {

			case ContentSource.MultipartSource(Object x) -> {
				yield x;
			}

			case ContentSource.FileSource(Object y) -> {
				yield y;
			}

		};
	}

}

If the classes and naming looks off its because I extracted it from my work codebase and only added what was missing to make it works.

Once Eclipse is upgraded, everything works fine!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants