I've got a Kotlin Compose Desktop application that I would like to create a custom JRE for to reduce its size. Currently after the compilation it's around 160MB (I guess because I use the JDK to compile it).
I've found that I can use the jre
command line tool to inspect it for which modules I need to include in the custom JRE.
However, I cannot figure out which file exacly I need to inspect. I'v tried to do this with the *.exe
, but it fails as not being a *.zip
. Then I tried it with a MyApp.1.0-SNAPSHOT.jar
, but this is apparently also the wrong file:
Unable to derive module descriptor for: [file-path] ComposableSingletons$MainKt.class found in top-level directory (unnamed package not allowed in module)
So, now I think I probably need to compile the application differently to get an inspectable *.jar
file as a result.
Do you know how can I do this or which file I should inspect to get the list of modules my custom JRE needs to contain?
Here's its build.gradle.kt
configuration:
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
// https://github.com/JetBrains/compose-multiplatform/releases
kotlin("jvm") version "2.0.20"
kotlin("plugin.compose") version "2.0.20"
// https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-compatibility-and-versioning.html#jetpack-compose-and-compose-multiplatform-release-cycles
id("org.jetbrains.compose") version "1.6.11"
}
group = "com.me"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
google()
}
dependencies {
implementation(compose.desktop.currentOs)
// other libraries I use...
}
compose.desktop {
application {
mainClass = "MainKt"
// https://www.oracle.com/in/java/technologies/downloads/#java21
javaHome = System.getenv("JDK_21")
jvmArgs += listOf("-Xmx2G")
nativeDistributions {
targetFormats(TargetFormat.Exe)
packageVersion = "1.2.3"
packageName = "MyApp-v$packageVersion"
includeAllModules = true
}
buildTypes.release.proguard {
isEnabled = false
}
}
}
tasks.wrapper {
// https://gradle.org/releases/
gradleVersion = "8.9"
// You can either download the binary-only version of Gradle (BIN) or
// the full version (with sources and documentation) of Gradle (ALL)
distributionType = Wrapper.DistributionType.ALL
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_21)
}
target {
compilations.all {
compileTaskProvider.configure {
compilerOptions {
// https://www.oracle.com/ca-en/java/technologies/java-se-support-roadmap.html
if (this is KotlinJvmCompilerOptions) {
jvmTarget = JvmTarget.JVM_21
}
}
}
}
}
sourceSets {
val test by getting {
dependencies {
// https://mvnrepository.com/artifact/io.kotest/kotest-framework-engine-jvm
implementation("io.kotest:kotest-framework-engine-jvm:5.9.1")
// https://mvnrepository.com/artifact/io.kotest/kotest-runner-junit5-jvm
implementation("io.kotest:kotest-runner-junit5-jvm:5.9.1")
// https://mvnrepository.com/artifact/io.kotest/kotest-assertions-core
implementation("io.kotest:kotest-assertions-core:5.9.1")
}
}
}
}
based on this document, compose multiplatform uses jlink to make a custom distributable that comes in with a custom JRE which only includes modules needed in your app. You can create this installer via packageMsi
, packageDmg
or packageDeb
gradle tasks available in compose desktop gradle plugin. You can also run your app with the custom JRE without creating an installer with runDistributable
. The document itself states that if things go wrong with JLink, you can run the suggestModules
task to further help you in finding the right jvm modules for your app.