Can't launch jar built using Gradle


#1

Hello,

I’m trying not to use fat jar as far as it’s getting too big and uploading it every time to the server takes quite a long time. So, I’m building usual jars and copy all the dependencies into separate folder.
Here’s a part of Gradle file

    task copyJarToBundle(type: Copy,) {
        into "$buildDir/bundle"
        from jar
    }

    task copyLibsToBundle(type: Copy, dependsOn: 'copyJarToBundle') {
        into "$buildDir/bundle/libs"
        from configurations.runtimeClasspath
    }
    build.dependsOn(copyLibsToBundle)

I’m launching my jar and specifying classpath to stdlib:

java -jar myjar-1.0.0.jar -cp "libs/kotlin-stdlib-1.3.10.jar"

But I’m still receiving an error that looks like missing kotlin-runtime:

Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/functions/Function1
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
        at java.lang.Class.privateGetMethodRecursive(Unknown Source)
        at java.lang.Class.getMethod0(Unknown Source)
        at java.lang.Class.getMethod(Unknown Source)
        at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.functions.Function1
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 7 more

Am I missing something?


#2

You can’t use -jar and -cp. If you’re using -jar, you need either fat jar or Class-Path entry in main jar manifest which will point to other jars (I suggest this approach if you want clickable jar). The most versatile solution is just specify main class: java -cp myjar-1.0.0.jar:libs/kotlin-stdlib-1.3.10.jar my.MainKt. Also note that you can use wildcards. I’m using the following approach: copy all jars into lib directory and running JVM with the following line: java -cp 'lib/*' my.MainKt. Also note single quotes, that '*' must be passed to JVM, not expanded by your shell.

Also you can use distribution plugin instead of writhing your own packager. Something like that:

apply plugin: 'distribution'

distributions {
  main {
    contents {
      into('lib') {
        from(jar)
        from(project.configurations.runtime)
      }
    }
  }
}

#3

Wow. That’s amazing! Thank you so much @vbezhenar for this valuable info!
I will give it a try and come back with a report.


#4

Works like a charm!
I didn’t use distributions plugin as far as it produces some kind of fat jar and I usually need only 1 jar from all the distribution.

But, the solution with starting class directly without “jar” is great.

Thank you so much!