76

I understand this question has been asked before, but none of the information there has helped me.

Here is my situation: I can't run a compiled Kotlin class. When I try to run it like I would a normal java class I get the following:

C:\Users\User\Desktop>java _DefaultPackage

Exception in thread "main" java.lang.NoClassDefFoundError: jet/runtime/Intrinsics
    at _DefaultPackage.main(Finder.kt)
Caused by: java.lang.ClassNotFoundException: jet.runtime.Intrinsics
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    ... 1 more

This led me to believe that the Kotlin runtime was simply missing, given that output. So I tried the following:

C:\Users\User\Desktop>java -cp kotlin-runtime.jar _DefaultPackage

Error: Could not find or load main class _DefaultPackage

Which made me think that maybe I needed to add the class file to my declared classpath so:

C:\Users\User\Desktop>java -cp kotlin-runtime.jar';_DefaultPackage.class _DefaultPackage

Error: Could not find or load main class _DefaultPackage

What am I missing?

Jesan Fafon
  • 2,234
  • 1
  • 25
  • 29

5 Answers5

137

Knowing the Name of Your Main Class

To run a Kotlin class you are actually running a special class that is created at the file level that hold your main() and other functions that are top-level (outside of a class or interface). So if your code is:

// file App.kt
package com.my.stuff

fun main(args: Array<String>) {
  ...
}

Then you can execute the program by running the com.my.stuff.AppKt class. This name is derived from your filename with Kt appended. You can change the name of this class within the file by adding this file-targeted annotation:

@file:JvmName("Foo")  

You can also put your main() into a class with a companion object and make it static using the JvmStatic annotation. Therefore your class name is the one you chose:

// file App.kt
package com.my.stuff

class MyApp {
    companion object {
        @JvmStatic fun main(args: Array<String>) {
          ...
        }
    }
}

Now you just run the class com.my.stuff.MyApp

What other JAR files do I need?

You need your application JAR and any dependencies. For Kotlin specific JARs when outside of Maven/Gradle you need a Kotlin distribution which contains:

  • kotlin-stdlib.jar (the standard library)
  • kotlin-reflect.jar only if using Kotlin reflection
  • kotlin-test.jar for unit tests that use Kotlin assertion classes

Running from Intellij

If in Intellij (if it is your IDE) you can right click on the main() function and select Run, it will create a runtime configuration for you and show the fully qualified class name that will be used. You can always use that if you are unsure of the name of the generated class.

Running from Gradle

You can also use the Gradle Application plugin to run a process from Gradle, or to create a runnable system that includes a zip/tgz of your JAR and all of its dependencies, and a startup script. Using the example class above, you would add this to your build.gradle:

apply plugin: 'application'

mainClassName = 'com.my.stuff.AppKt'

// optional:  add one string per argument you want as the default JVM args
applicationDefaultJvmArgs = ["-Xms512m", "-Xmx1g"] 

And then from the command-line use:

// run the program
gradle run

// debug the program
gradle run --debug-jvm

// create a distribution (distTar, distZip, installDist, ...)
gradle distTar

Running Directly from Java Command-line

If you have a runnable JAR, and assuming KOTLIN_LIB points to a directory where Kotlin runtime library files reside:

java -cp $KOTLIN_LIB/kotlin-stdlib.jar:MyApp.jar com.my.stuff.AppKt

See the notes above about other JAR files you might need. A slight variation if you have a runnable JAR (with the manifest pointing at com.my.stuff.AppKt as the main class):

java -cp $KOTLIN_LIB/kotlin-stdlib.jar -jar MyApp.jar

Running using the Kotlin command-line tool

If you install Kotlin tools via Homebrew or other package manager. (on Mac OS X brew update ; brew install kotlin) Then it is very simple to run:

kotlin -cp MyApp.jar com.my.stuff.AppKt

This command adds the stdlib to the classpath provided, then runs the class. You may need to add additional Kotlin libraries as mentioned in the section above "Running from Java."

Creating runnable JAR with the Kotlin compiler

This is not very common since most people use other build tools, but the Kotlin compiler can create a runnable Jar that solves this for you (see http://kotlinlang.org/docs/tutorials/command-line.html) when it bundles the runtime and your code together. Although this isn't as common when using tools such as Maven and Gradle, or IDE builds. Then run using the normal Java:

java -jar MyApp.jar
Jayson Minard
  • 84,842
  • 38
  • 184
  • 227
  • 4
    As of one year later, apparently someone at jetbrains decided that the T in KT shouldn't be uppercase. – Cubic Dec 27 '16 at 23:12
  • 2
    What would be the `mainClassName` to use with the application plugin if you don't specify a package name in `App.kt`? (As you don't have to with Kotlin.) – sschuberth Apr 02 '17 at 08:48
  • @sschuberth it is very bad to put anything in a default package, the rules change for resolution of other classes and it is considered a bad practice (other than maybe in scripting use cases). The answer is just `AppKt` without a package prefix, but I won't add that to the answer above. – Jayson Minard Apr 16 '17 at 14:37
  • 1
    the `public` qualifier for your `main` top-level function is redundant, everything is public by default – afollestad May 04 '18 at 17:45
  • What if my code has no `package` line at the top? – hippietrail Jun 01 '21 at 04:34
  • 1
    @hippietrail then you just use the class name without any package prefix. If it is a file named `Main.kt` without a package statement the class is just `MainKt` with no package prefix. If it is a class `MyMain` in whatever file with no package prefix, then the class to run is `MyMain`. ... – Jayson Minard Jun 02 '21 at 16:56
  • Is `$KOTLIN_LIB` normally there or is this something we're assuming the user sets up? I'm on macOS Ventura/IntelliJ IDEA 2023.1.1 (Community Edition) and it doesn't exist here. – hippietrail May 05 '23 at 10:01
  • A few tips for people that hit this and still get stuck: 1. If `$KOTLIN_LIB` is not set use `find` in your home dir. For me on macOS Ventura `~/Library/Developer/Xamarin/android-sdk-macosx/cmdline-tools/1.0/lib/external/kotlin-plugin-ij/Kotlin/kotlinc/lib/kotlin-stdlib.jar` also at `.../2.1/lib/...` 2: The name of the class will be uppercased. My file is called `commonMain.kt` and in my `build.gradle.kts` is referred to as `commonMain` but to run from the commandlike I have to use `CommonMainKt` – hippietrail May 05 '23 at 10:53
19

You can compile using kotlinc as follows:

$ kotlinc hello.kt -include-runtime -d hello.jar

and then you can run jar file as follows:

$ java -jar hello.jar

Akshar Patel
  • 8,998
  • 6
  • 35
  • 50
5

I struggled with this for a while as well. You're close, you just need to include your jar in the classpath and pass the qualified name of your "main" class as the primary argument to java.

ajselvig
  • 688
  • 1
  • 5
  • 12
2

There are a couple of ways to run Kotlin from the command line, depending on whether you're using the Java bytecode compiler (kotlinc) or the native compiler (kotlinc-native).

If you get an error message about -include-runtime, read the message carefully. You may be using the Kotlin native compiler instead of the Kotlin bytecode compiler. If you want to use the native compiler, see the second section below.

kotlinc (Java bytecode)

It's important to consider that you may not be in the same folder as your main.kt when you try to run your project, and it's not always clear how to tell Kotlin (or Java) to find it.

Assuming that:

  • You're trying to compile and run from a Windows command prompt.
  • You have this project structure (after IntelliJ Idea sets up a command-line Kotlin project):
MyNiftyProject
  src
    main
      kotlin
        main.kt
  • You're in the project root.
  • And you have this main.kt file:
fun main(args: Array<String>) {
    println("Hello World!")
}

Compile like this:

kotlinc src/main/kotlin/main.kt -include-runtime -d MyNiftyProject.jar

This puts MyNiftyProject.jar in the root of your project.

Then run like this using the java command-line tool:

java -jar MyNiftyProject.jar

Or run like this using the kotlin command-line tool:

kotlin -classpath MyNiftyProject.jar MainKt

kotlinc-native

For native code, the process is somewhat simpler. Using the same setup as above:

kotlinc-native src/main/kotlin/main.kt -o MyNiftyProject

This puts MyNiftyProject.exe in the root of your project.

Then you just run it as a normal Windows executable:

MyNiftyProject.exe
Ryan Lundy
  • 204,559
  • 37
  • 180
  • 211
0

if you are using a jar file that is generated from IntellijeIdead, you should run the kotlin file like java files but consider that kotlin file name will be something like that : your file: test.kt your output in the jar: testKt

java -cp file.jar yourPackage.testKt
behrad
  • 1,228
  • 14
  • 21