Jar file only works with Java classes but not with Kotlin


#1

Hello,

since I found Kotlin pretty useful for programming Android-apps, I tried programming some pretty simple command line programm I found in the reference on the Kotlin site. Running the whole thing inside IntelliJ has never been a problem, but creating a .jar file by building an artifact is quite tricky.

  • I have not been able to choose a kotlin file / class as main class, I solved it by using a Java class as main class
  • The second problem is, that as soon as I am trying to access a method from the Kotlin class through the Java class I get the following error(s):
    Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics at de.DJJD.programme.myFunctions.cases(myFunctions.kt) at de.DJJD.programme.main.main(main.java:9) Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 2 more

So im trying to access the myFunctions.kt class using the following code
public class main { public static void main(String[] args) { myFunctions f = new myFunctions(); f.cases(1); } }

Once I put some simple code into a java class that just prints out the the parameter coming from the main class, it works!
What could be the problem?
I already added the KotlinJavaRuntime lib in Project Structure | Artifacts and tried it using Gradle as shown on the reference page, but it does never find the classes as soon as I use Kotlin…

Thanks for your help,
Julian

If someone could provide me some working (/compilable) Kotlin project as a sample which I can import and see what settings I have to use, that would be great!


#2

I had this problem too. If you have a Launcher.kt file containing only a main() function, it will not compile into a Launcher.class but rather LauncherKt.class. Try concatenating"Kt" when specifying the main() class.


#3

If I just use
fun main() { val f = myFunctions() f.cases(1) }
I cannot even test it in IntelliJ since it does not find a main class. Any other suggestions?


#4

Or add this line to the top of the file to tell it the class name to generate:

@file:JvmName(“Launcher”)


#5

This does not work properly, the class is still named MainKt.class. There must be a different soulution to make IntelliJ let me choose a Kotlin file as main class in the project structure. The problem seems to be that kotlin classes (or main functions?) are not recognised as classes in the .jar


#6

Where is your args? If your file containing the main method was Launcher.kt, this is what it should contain:

fun main(args: Array<String>) {
    val f = myFunctions()
    f.cases(1)
}

It will then compile to a class called LauncherKt containing the main() method, and simply right-clicking the main() method should give you the option to run or debug it.


#7

That works so far, but if I run the .jar I get the following error (I translated it, so it could be different in the english version): Mainclass de.DJJD.programme.MainKt could not be found or loaded
Edit: attatchment


#8

And you added the args: Array<String> argument to the main() function? If so, show us the name and contents of the entire Kotlin file containing the main() function.


#9

main.kt:
package de.DJJD.programme

fun main(args: Array<String>) {
    val f = myFunctions()
    f.cases(1)
}

myFunctions.kt:
package de.DJJD.programme

class myFunctions {
    fun cases(obj: Any) {
        when (obj) {
            1 -> print("One")
            "Hello" -> print("Greeting")
            is Long -> print("Long")
            !is String -> print("Not a string")
            else -> print("Unknown")
        }
    }
}

#10

Okay I would highly advise making your class names not camelCase, but rather PascalCase (e.g. MyFunctions and Main.kt). If you are to stick with camelCase, it would be called mainKt, not MainKt.

But you REALLY should make PascalCase the names of your classes, and camelCase the names of properties, functions, and variables.


#11

Thanks for your advice. Does that mean that in Main.kt the fun main() should be fun Main() or not?
Btw it does still not work. Same error as before

Edit: Is it possible that I have to change the classpath?


#12

the main() function is camelCase (since it is one word it is all lowercase). The file, which you happen to pick the name Main, is pascalCase. You could make the file/class any other name. It does not have to be Main.


#13

After you change the name of the class from main.kt to Main.kt, yes. You would specify it as MainKt.


#14

That is what it actually looks like. But I am still getting the same error, although I can now choose the Main.kt from the IDE (Project Structure > Artifacts…)
“The .jar file” simply does not find the main class…


#16

Just curious: what actually is in the generated JAR? You can rename it from .jar to .zip and open it to look into the file. You should then see which classes are there and which aren’t.


#17

There is a META-INF folder including the manifest, and kotlin-reflect.jar as well as kotlin-runtime.jar but no classes…

If I copy the whole de folder into that zip and debug it in intellij after that I get the following error:
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics at de.DJJD.programme.MainKt.main(Main.kt) Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 1 more


#18

You could try this one here https://github.com/dittert/minimalkotlin to compare what is different in your setup.

git clone https://github.com/dittert/minimalkotlin.git will clone it locally. Then, you can open it up in IntelliJ.

I just looked at your screenshots: That can’t work. You do not include any of your classes. Here is how it is supposed to look like. To add your classes, you can click on the plus button and select Module output.

And your NoClassDefFoundError errors are probably because you include the Kotlin runtime into the JAR instead of the contents of their JARs. Java does not support reading library JARs from inside a JAR file.

To solve that:

  1. Remove KotlinJavaRuntime (Project Library) on the left hand side (i.e. future contents of the JAR file)
  2. Select KotlinJavaRuntime (Project Library) on the right hand side
  3. Select Extract Into Output Root from the context menu

IDEA will then extract the contents of the library JARs and put those files into the JAR file that is generated on build. You should then be able to run it with java -jar <path to jar file>.

Hope that helps!


#19

Gonna try that later. But I found out, how to get the classes into the jar file: something was missing in the project structure, now I added that from the right side to the left and now they are inside the .jar, but still having the NoClassDef error…


#20

You got some “extracted…” files there which I don’t have. What I’ve found out is that if I delete these 2 files and add the KotlinJavaRuntime from the right instead, I get the same error. So how did you get the “extracted” files there?!

Edit: Now I found out how to get these files there, but I don’t have such a lib-folder, so where is it from? How can I get it? And why does it only work with these extracted .jars and not the KotlinJavaRuntime?!


#21

Sorry, but you’re too fast. I updated my answer above with all details. :slight_smile: