Skip to content

DCEVM reloading fails with NoSuchMethodError when changing lambda captures in active stack frame #534

@natanfudge

Description

@natanfudge

Steps to reproduce

  1. Follow the instructions from Youtrack. In short:
  • Setup an "Enhanced Class Redefinition" launch configuration, i.e. set VM options to
-XX:+AllowEnhancedClassRedefinition -XX:HotswapAgent=fatjar

Image

  • Add the hotswap-agent-2.0.2.jar file from here into the lib/hotswap directory in the JBR, and rename it into hotswap-agent.jar.
  • You can use the -core hotswap agent, or no hotswap agent at all, and it will crash all the same.
  1. Run this code in debug mode in Intellij IDEA:
public class TestHotReload {
    public static void main(String[] args) throws InterruptedException {
        while (true) {
            Thread.sleep(100);
            var x = 10;
            javaLambda(() -> {
                System.out.println(x);
                System.out.println("Halo");
            });
        }
    }

    private static void javaLambda(Runnable lambda) {
        lambda.run();
    }
}
  1. Comment out the line
System.out.println(x);

By doing this you have made the lambda no longer capture x, and the function signature of the lambda changes from (int) to ()
4. Reload changed classes, using a hotkey, or the new integrated Idea popup button.
5. Observe crash:

Exception in thread "main" java.lang.NoSuchMethodError: 'void TestHotReload.lambda$main$0(int)'
	at TestHotReload.javaLambda(TestHotReload.java:15)
	at TestHotReload.main(TestHotReload.java:7)
  • You can write it in Kotlin, or add instead of removing capture, and it will crash all the same.

Expected Behavior

The code reloads successfully; The code continues executing without running System.out.println(x); i.e. without printing x.

Actual Behavior

Program crashes with NoSuchMethodError on reload with a lambda capture change. In Kotlin (and sometimes in Java) these changes are very common, so "Enhanced Class Redefinition" does not work in most cases.

Environment

Using Windows 11, latest JBR Release 21.0.6b631.42. Using Gradle if the matters.

Notes

It doesn't make much sense; It seems like everyone, especially Jetbrains, would be encountering this all the time, but I could not find any mention of this issue anywhere, and I remember encountering this issue all the way back when I tried DCEVM in 2018. Maybe there is some workaround or configuration everyone uses?
EDIT: Here, I found some OG issue in DCEVM dcevm/dcevm#174, Barteks being quite right:

With this issue, hotswap becomes less and less relevant with code that actually uses java 8+ features. And it's likely to become even more of a problem with future java features.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions