JVM application¶
Use the jvm/app product type in a module to build a JVM console or desktop application.
Module layout¶
Here is an overview of the module layout for a JVM application:
my-module/
├─ resources/ # (1)!
│ ╰─ logback.xml # (2)!
├─ src/
│ ├─ main.kt
│ ╰─ Util.java # (3)!
├─ test/
│ ╰─ MainTest.java # (4)!
│ ╰─ UtilTest.kt
├─ testResources/
│ ╰─ logback-test.xml # (5)!
╰─ module.yaml
- Resources placed here are copied into the resulting jar.
- This is just an example resource and can be omitted.
- You can mix Kotlin and Java source files in a single module, all in the
srcfolder. - You can test Java code with Kotlin tests or Kotlin code with Java tests.
- This is just an example resource and can be omitted.
Maven compatibility layout for JVM-only modules
If you're migrating from Maven, you can also configure the Maven-like layout
Entry point¶
By default, the entry point of JVM applications (the main function) is expected to be in a main.kt file
(case-insensitive) in the src folder.
The main function must either have no parameters or one Array<String> parameter (representing the command line arguments).
This can be overridden by specifying a main class explicitly in the module settings:
product: jvm/app
settings:
jvm:
mainClass: org.example.myapp.MyMainKt
Note
In Kotlin, unlike Java, the main function doesn't have to be declared in a class, and is usually at the top level
of the file. However, the JVM still expects a main class when running any application. Kotlin always compiles
top-level declarations to a class, and the name of that class is derived from the name of the file by capitalizing
the name and turning the .kt extension into a Kt suffix.
For example, the top-level declarations of myMain.kt will be in a class named MyMainKt.
Packaging¶
You can use the build command to produce a regular JAR of your application's code, or the package
command to produce an Executable JAR.
The executable JAR format is developed by the Spring team, hence why you might see the
spring-boot-loader embedded in it.
That being said, this format is a universal packaging solution suitable for any JVM application.
It provides a convenient, runnable self-contained deployment unit that includes all necessary dependencies.
Why not create an Über JAR (a.k.a Fat JAR)?
The usual "Über JAR" (a.k.a "Fat JAR") format is quite popular: it just contains the contents of all your dependency JARs, merge with your own classes and resources. This approach has issues that stem from this unpacking/repacking of JARs. For example:
- signature files are no longer valid after the merge, which can render some security libraries invalid
META-INF/MANIFEST.MFfiles are duplicated in many JARs, and thus need to be discarded or merged- service loader resources also may have conflicting names and need to be merged
- any other duplicate class/resource file need to be handle in custom ways, which have to be configurable
The executable JAR format doesn't have these problems because it keeps the original JARs intact – it just embeds them and loads them on-demand.