spring-boot: Spring Boot 3 Native Fails to Start with Kotlin @JvmStatic Main Method

Bug Report for Spring Boot 3 Native (GraalVM 22.3) Having a simple Spring Boot application (generated on start.spring.io), changing the main class to:

@SpringBootApplication(proxyBeanMethods = false)
class DemoApplication {
  companion object {
    @JvmStatic
    fun main(args: Array<String>) {
      runApplication<DemoApplication>(*args)
    }
  }
}

And building the native image (via ./gradlew nativeCompile) gives you an executable that fails to start with:

2022-10-29T11:11:27.459+02:00 ERROR 8553 --- [           main] o.s.boot.SpringApplication               : Application run failed

java.lang.IllegalArgumentException: Could not find class [com.example.demo.DemoApplication$Companion__ApplicationContextInitializer]
        at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:333) ~[na:na]
        at org.springframework.context.aot.AotApplicationContextInitializer.instantiateInitializer(AotApplicationContextInitializer.java:80) ~[demo:6.0.0-RC2]
        at org.springframework.context.aot.AotApplicationContextInitializer.initialize(AotApplicationContextInitializer.java:71) ~[demo:6.0.0-RC2]
        at org.springframework.context.aot.AotApplicationContextInitializer.lambda$forInitializerClasses$0(AotApplicationContextInitializer.java:61) ~[demo:6.0.0-RC2]
        at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:603) ~[demo:3.0.0-RC1]
        at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:383) ~[demo:3.0.0-RC1]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[demo:3.0.0-RC1]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[demo:3.0.0-RC1]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) ~[demo:3.0.0-RC1]
        at com.example.demo.DemoApplication$Companion.main(DemoApplication.kt:15) ~[na:na]
        at com.example.demo.DemoApplication.main(DemoApplication.kt) ~[demo:na]
Caused by: java.lang.ClassNotFoundException: com.example.demo.DemoApplication$Companion__ApplicationContextInitializer
        at java.base@19.0.1/java.lang.Class.forName(DynamicHub.java:1132) ~[demo:na]
        at org.springframework.util.ClassUtils.forName(ClassUtils.java:283) ~[na:na]
        at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:323) ~[na:na]
        ... 10 common frames omitted

Let me know if you need more information. Thanks.

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 5
  • Comments: 32 (11 by maintainers)

Most upvoted comments

@kkocel I played around with your main branch to understand why it happens and noticed that when I only downgrade to Kotlin 1.8.22 your example builds and run without the exception.

kotlin("jvm") version "1.8.22"
kotlin("plugin.spring") version "1.8.22"
docker run --rm -p 8080:8080 docker.io/library/classnotfoundrepero:0.0.1-SNAPSHOT

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.1.2)

2023-08-22T14:38:01.076Z  INFO 1 --- [           main] c.e.c.ClassnotfoundreperoApplicationKt   : Starting AOT-processed ClassnotfoundreperoApplicationKt using Java 17.0.7 with PID 1 (/workspace/com.example.classnotfoundrepero.ClassnotfoundreperoApplicationKt started by cnb in /workspace)
2023-08-22T14:38:01.076Z  INFO 1 --- [           main] c.e.c.ClassnotfoundreperoApplicationKt   : No active profile set, falling back to 1 default profile: "default"
2023-08-22T14:38:01.116Z  INFO 1 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 1 endpoint(s) beneath base path '/actuator'
2023-08-22T14:38:01.136Z  INFO 1 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port 8080
2023-08-22T14:38:01.137Z  INFO 1 --- [           main] c.e.c.ClassnotfoundreperoApplicationKt   : Started ClassnotfoundreperoApplicationKt in 0.074 seconds (process running for 0.079)

I made a project that reproduces this issue - it has two branches: one with Kotlin main and another with Java main. Both fail with the same error. https://github.com/kkocel/classnotfoundrepero

Got it. Thanks for the link. 🙏

@kkocel thanks, but, as far as I can tell, the issue as originally reported still occurs with Spring Boot 3.2 and Kotlin 1.9.20. In fact, it’s got slightly worse as the error message is no longer as helpful as it was:

> Task :nativeRun FAILED

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.2.0)

2023-12-04T12:25:16.225Z ERROR 83509 --- [           main] o.s.boot.SpringApplication               : Application run failed

java.lang.IllegalStateException: You are starting the application with AOT mode enabled but AOT processing hasn't happened. Please build your application with enabled AOT processing first, or remove the system property 'spring.aot.enabled' to run the application in regular mode
        at org.springframework.util.Assert.state(Assert.java:76) ~[na:na]
        at org.springframework.boot.SpringApplication.addAotGeneratedInitializerIfNecessary(SpringApplication.java:440) ~[gh-32918:3.2.0]
        at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:396) ~[gh-32918:3.2.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) ~[gh-32918:3.2.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1342) ~[gh-32918:3.2.0]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1331) ~[gh-32918:3.2.0]
        at com.example.gh32918.Gh32918Application$Companion.main(Gh32918Application.kt:15) ~[na:na]
        at com.example.gh32918.Gh32918Application.main(Gh32918Application.kt) ~[gh-32918:na]

I think we should consider refining or reverting https://github.com/spring-projects/spring-boot/pull/38188, particularly while this issue is unresolved.

Have the same problem. No luck with workarounds that were mentioned here.

java.lang.IllegalArgumentException: Could not find class [xyz.app.ApplicationKt__ApplicationContextInitializer]
        at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:333)
        at org.springframework.context.aot.AotApplicationContextInitializer.instantiateInitializer(AotApplicationContextInitializer.java:80)
        at org.springframework.context.aot.AotApplicationContextInitializer.initialize(AotApplicationContextInitializer.java:71)
        at org.springframework.context.aot.AotApplicationContextInitializer.lambda$forInitializerClasses$0(AotApplicationContextInitializer.java:61)
        at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:605)
        at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:385)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:309)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1304)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1293)
        at xyz.app.ApplicationKt.main(Application.kt:13)
Caused by: java.lang.ClassNotFoundException: xyz.app.ApplicationKt__ApplicationContextInitializer
        at java.base@17.0.6/java.lang.Class.forName(DynamicHub.java:1132)
        at org.springframework.util.ClassUtils.forName(ClassUtils.java:283)
        at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:323)

build.gradle.kts

plugins {
    id("org.springframework.boot") version "3.0.5"
    id("io.spring.dependency-management") version "1.0.13.RELEASE" 
    kotlin("jvm") version "1.8.10" 
    kotlin("plugin.spring") version "1.8.10" 
    kotlin("kapt") version "1.8.10"
}
...

tasks.bootBuildImage {
    builder.set("paketobuildpacks/builder:tiny")

    environment.set(
        mapOf(
            "BP_NATIVE_IMAGE" to "true",
            "BP_NATIVE_IMAGE_BUILD_ARGUMENTS" to
                    """
                    --verbose
                    --no-fallback
                    --initialize-at-build-time=org.slf4j.LoggerFactory,ch.qos.logback
                    --trace-class-initialization=ch.qos.logback.classic.Logger 
                    --initialize-at-run-time=io.netty
                """.trimIndent()
        )
    )
}

The workaround doesn’t work for me since I have to set the main class in bootRun task

This shouldn’t be necessary. bootRun should be automatically configured to use the right main class when using either a companion object or a package-level function.