Команда Kotlin для запуска JAR из командной строки

Вопрос или проблема

Я озадачен сообщением об ошибке, которое получаю, когда пытаюсь скомпилировать очень простую программу в jar-файл и запустить ее из командной строки. Следующее работает нормально:

fun main() {
    printf("Hello, world!")
}

Я могу скомпилировать и выполнить это так:

$ kotlinc -d hello.jar Hello.kt
$ kotlin hello.jar
Hello, world!
$

Однако, если я сделаю следующее тривиальное изменение в коде:

fun main(args: Array<String>) {
    println("Hello, world!")
}

Теперь я получаю ошибку:

$ kotlinc -d hello.jar Hello.kt
$ kotlin hello.jar
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
    at HelloKt.main(Hello.kt)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:569)
    at org.jetbrains.kotlin.runner.AbstractRunner.run(runners.kt:70)
    at org.jetbrains.kotlin.runner.Main.run(Main.kt:183)
    at org.jetbrains.kotlin.runner.Main.main(Main.kt:193)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
    ... 8 more
$ 

Странно, но я могу распаковать jar-файл и запустить его содержимое без проблем:

$ jar xf hello.jar
$ kotlin HelloKt
Hello, world!
$

Так почему я не могу запустить Kotlin-приложение из jar-файла, если его функция main принимает аргументы?

Я пробовал Kotlin 1.9.24 и 2.0.21 с Java 11, 17 и 21 на Ubuntu Linux.

Я нашел ответ, поэтому я оставлю его здесь на случай, если кто-то другой столкнется с этой проблемой в будущем.

Команда kotlin hello.jar эквивалентна java -jar hello.jar – библиотека Kotlin stdlib должна присутствовать. Вот соответствующий фрагмент из вывода команды kotlin -help:

app.jar   Запускает данный JAR-файл так же, как и 'java -jar'
          (аргументы компилятора игнорируются, и библиотека Kotlin stdlib не добавляется в classpath)

С другой стороны, команда kotlin HelloKt автоматически использует библиотеку Kotlin stdlib.

Таким образом, чтобы запустить jar-файл, вам следует скомпилировать его с помощью kotlinc -include-runtime.

Ответ или решение

Конечно! Вот полное объяснение вашей проблемы и решение на русском языке.


Проблема: Ошибка при запуске JAR файла на Kotlin

Вы столкнулись с ошибкой при попытке запустить JAR файл, скомпилированный с использованием функции main, принимающей аргументы. При запуске возникала следующая ошибка:

Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics

Что произошло

Когда вы использовали команду kotlin hello.jar, это эквивалентно команде java -jar hello.jar. В этом случае стандартная библиотека Kotlin (kotlin-stdlib) не добавляется в classpath автоматически. Поэтому при вызове вашего приложения, если оно зависит от стандартной библиотеки, возникает ошибка NoClassDefFoundError.

Ваш первоначальный вариант кода:

fun main() {
    println("Hello, world!")
}

Здесь вызывается функция println, которая не требует дополнительных библиотек, поэтому выполнение проходит без ошибок.

Тем не менее, когда вы изменили сигнатуру main на:

fun main(args: Array<String>) {
    println("Hello, world!")
}

Код пытается использовать функционал, требующий наличия стандартной библиотеки. Отсутствие этой библиотеки в classpath приводит к ошибке, которую вы наблюдаете.

Решение

Чтобы успешно запустить ваш JAR файл, вам нужно включить стандартную библиотеку Kotlin при компиляции. Вы можете это сделать с помощью флага -include-runtime:

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

После этого, когда вы запустите ваш JAR файл с помощью:

kotlin hello.jar

Проект будет собран корректно, и ошибка не возникнет. Вы сможете видеть вывод:

Hello, world!

Заключение

Теперь вы знаете, что для успешного запуска JAR файлов на Kotlin, требуется учитывать использование стандартной библиотеки. Если вы столкнетесь с подобными проблемами в будущем, убедитесь, что стандартные библиотеки Kotlin включены при компиляции вашего приложения.

Если у вас есть дополнительные вопросы или нужна помощь, не стесняйтесь обращаться!


Надеюсь, это поможет вам разобраться с вашей проблемой!

Оцените материал
Добавить комментарий

Капча загружается...