Вопрос или проблема
Я озадачен сообщением об ошибке, которое получаю, когда пытаюсь скомпилировать очень простую программу в 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 включены при компиляции вашего приложения.
Если у вас есть дополнительные вопросы или нужна помощь, не стесняйтесь обращаться!
Надеюсь, это поможет вам разобраться с вашей проблемой!