6

I have mixed Java & Kotlin code in a demo project which I want to run from command line. For only java, I am able to run the program with java -jar foo.jar but when I use any class from Kotlin code, it generates java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics

I have tried different solutions and checked the jar file. It contains both the classes but I guess kotlin-runtime is missing from jar.

Here is build.gradle file

plugins {
    id 'java-library'
    id 'org.jetbrains.kotlin.jvm'
}

sourceSets {
    main.java.srcDirs += 'src/main/kotlin/'
    test.java.srcDirs += 'src/test/kotlin/'
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    testImplementation 'junit:junit:4.12'
}

jar {
    manifest {
        attributes 'Main-Class': 'com.mallaudin.App'
    }
    from {
        configurations.compile.collect {
            it.isDirectory()? it: zipTree(it)
        }
    }
}

Content of generated jar file

.
├── com
│   └── mallaudin
│       ├── App.class
│       └── User.class
└── META-INF
    ├── basics.kotlin_module
    └── MANIFEST.MF

Content of MANIFEST.MF

Manifest-Version: 1.0
Main-Class: com.mallaudin.App

Exception I get when I run jar form command line

allaudin@geek ~/Desktop/KotlinLab (master) $ java -jar basics/build/libs/basics.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
    at com.mallaudin.User.<init>(User.kt)
    at com.mallaudin.App.main(App.java:5)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:190)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
    ... 2 more
5
  • 1
    Don't use images. Copy and paste the text in your question. Commented Dec 15, 2018 at 21:42
  • Can you please post the dependencies part of your build.gradle? I assume the kotlin runtime is not defined as a compile time dependency. Commented Dec 16, 2018 at 1:26
  • @ErikPragt kindly check updated question. Commented Dec 16, 2018 at 6:35
  • @ErikPragt I think the same but I have added the dependency. I don't know what's going on. Commented Dec 16, 2018 at 6:42
  • This is probably a pretty clear writeup" stackoverflow.com/questions/44493378/… Commented Dec 17, 2018 at 6:19

2 Answers 2

3

The issue is in the way you build your fat jar. While you use the more recent and recommended implementation scope for your dependencies, you are only adding to the fat jar the content of the compile configuration.

You should replace the configuration to be used in the fat jar by runtimeClasspath which is the full set of runtime components.

That is:

jar {
  manifest {
    attributes 'Main-Class': 'com.mallaudin.App'
  }
  from {
    configurations.runtimeClasspath.collect {
      it.isDirectory()? it: zipTree(it)
    }
  }
}  

Have a look at the documentation to understand the different dependency configurations for a java project.

Sign up to request clarification or add additional context in comments.

Comments

0

So, I have found a solution. In build.gradle file I have replaced implementation configuration with compile and it works now. I believe it should work with implementation too but it doesn't. Now the jar looks like this

.
├── com
├── kotlin
├── META-INF
└── org

5 Comments

Hi, I'm glad it works now, but that's what I said in my previous comment already ;-)
But why it doesn't work with implementation? Do you have any idea?
I'm pretty sure it will work with implementation too, but then you need to change this line: configurations.compile to also include implementation: configurations.implementation. Right now, you only include compilation scope, cause that was the 'old' way of doing things.
configurations.implementation is not allowed. I have checked it already.
I'm having the same problem. Switching from implementation to api didn't help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.