NoClassDefFoundError for standard Kotlin library in gradle build with Docker

I’m trying to build an executable jar from an extremely simple Kotlin application. Here is the code:

// org/example/App.kt
package org.example

import kotlin.random.Random

class App {
    fun run() {
        var x = 0L
        for (i in 2..100000) {
            x += Random.nextInt(i)
        }
        println(x)
    }
}

fun main() {
    App().run()
}

Here is my build.gradle.kts file:

plugins {
    alias(libs.plugins.jvm)
    application
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.apache.commons:commons-math3:3.6.1")
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)
    }
}

application {
    mainClass = "org.example.AppKt"
}

tasks.named<Jar>("jar") {
    manifest {
        attributes["Manifest-Version"] = "1.0"
        attributes["Main-Class"] = "org.example.AppKt"
        attributes["Class-Path"] = configurations.compileClasspath.get().joinToString(" ") { it.name }
    }
}

When I run the gradle build task, and then run java -jar app/build/libs/app.jar, I get this output:

Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/random/Random
        at org.example.App.run(App.kt:9)
        at org.example.AppKt.main(App.kt:16)
        at org.example.AppKt.main(App.kt)
Caused by: java.lang.ClassNotFoundException: kotlin.random.Random
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
        ... 3 more

This is obviously an error in how I’m building the jar, as kotlin.random.Random is part of the standard library. I’ve searched high and low for information on this error, and everything is either outdated or just does not work for me. If anyone can advise me on what I’m doing wrong, I’d really appreciate it. I don’t think Docker is part of the issue, as I’m unable to run my jar when running the gradle build task directly, but in case it’s at all relevant, here is my Dockerfile as well:

FROM gradle:8.6.0-jdk11-alpine AS build
COPY --chown=gradle:gradle . /home/gradle/src
WORKDIR /home/gradle/src
RUN gradle build --no-daemon

FROM eclipse-temurin:11-jre

EXPOSE 8080

RUN mkdir /app

COPY --from=build /home/gradle/src/app/build/libs/*.jar /app/docker-test.jar

ENTRYPOINT ["java","-jar","/app/docker-test.jar"]

Historically, I’ve been building my jars using the Ktor plugin’s buildFatJar task, as I’ve never been able to get Gradle to successfully build a working jar. I’d like to finally learn what I’m doing wrong, and possibly be able to actually build something runnable with Gradle alone.

Gradle does not have a built-in support for such bad-practice fat jars.

If you really want to build one for whatever reason, I’d recommend you use the shadow plugin of John R. Engelman.

The application plugin is not building a fat jar, but a proper distribution with the libs and start scripts that put everything together.