spring-projects / spring-projects/spring-boot

Prevent initializers from being applied twice in AOT mode

Open
#32,262 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: blocked theme: aot type: enhancement
Dominant language
Java
Stars
81.5k
Forks
42.7k
Avg merge
2d 4h
Merged PRs (30d)
65

Description

Running the following application prints 2 times Foo constructor at startup while a single time as expected in regular mode.

@SpringBootApplication
public class CommandlinerunnerApplication {

	public static void main(String[] args) {
		SpringApplication app = new SpringApplication(CommandlinerunnerApplication.class);
		app.addInitializers((ApplicationContextInitializer<GenericApplicationContext>) context ->
				context.registerBean(Foo.class));
		app.run(args);
	}
}

public class Foo {

	public Foo() {
		System.out.println("Foo constructor");
	}
}

A look at the generated code shows that Foo__BeanDefinitions generated during AOT transformations based on the initializer is created as expected, but it seems the second invocation comes from the fact that SpringApplication#applyInitializers is still invoked at runtime.

Notice that on native, this second invocation fails with Runtime reflection is not supported for public com.example.commandlinerunner.Foo() because unlike the AOT generated one, it requires ExecutableMode#INVOKE reflection hints (not inferred because not needed by the AOT generated code which is fine with ExecutableMode#INTROSPECT).

Both issues should be solved by removing the second invocation of the initializers, but this need to be explored because it could involve unwanted side effects with some initializers.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at SpringApplication#applyInitializers and compare its runtime path with the AOT-generated Foo__BeanDefinitions path described in the report. Reproduce the application in regular and native modes, then trace why the initializer runs twice. Done means the duplicate construction and native reflection failure are addressed without unwanted initializer side effects.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring-boot
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.