Я только начал использовать Kotlin, и у меня возникли некоторые проблемы с пониманием того, как работают файлы JAR. У меня есть два файла:
привет.кт
class HelloWorld {
public fun speak() {
println("hello world")
}
}
main.kt
fun main() {
val hello = HelloWorld()
hello.speak()
}
Структура моего проекта:
root
|-hello.kt
|-main.kt
Мое намерение — создать приложение Kotlin, распределяя его классы среди отдельных файлов JAR. я использовал
kotlinc hello.kt -d hello.jar
kotlinc main.kt -cp hello.jar -include-runtime -d main.jar
для создания файлов JAR. Эти две команды выполняются без каких-либо ошибок. У меня возникли проблемы с пониманием того, как выполнить приложение.
До сих пор я пробовал
java -cp hello.jar -jar main.jar
для запуска приложения, но я получаю эту ошибку:
Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld
at MainKt.main(main.kt:2)
at MainKt.main(main.kt)
Caused by: java.lang.ClassNotFoundException: HelloWorld
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
... 2 more
Я также пытался следить за ответом на этот вопрос, который показывает ту же проблему, но работает
java -cp main.jar:hello.jar MainKt
дает мне следующую ошибку
Error: Could not find or load main class MainKt
Caused by: java.lang.ClassNotFoundException: MainKt
Я новичок в Kotlin и JVM в целом, но не могу найти решение.
Имеет ли файл с функцией main()
объявление package
вверху?
Во-первых, вы обычно используете инструмент сборки, такой как Gradle, чтобы выполнить компиляцию и упаковку за вас. Однако в целях обучения всегда приятно знать, как все устроено под капотом.
В вашем случае вы все правильно компилируете. Однако существуют проблемы с запуском приложения с помощью команды java
. Во-первых, вы не можете смешивать -cp
и -jar
, как указано в документации:
При использовании -jar указанный файл JAR является источником всех пользовательских классов, а другие параметры пути к классам игнорируются. Если вы используете файлы JAR, см. jar.
Короче говоря, вам нужно выбирать между использованием -jar
с исполняемым файлом jar, содержащим всю информацию о пути к классам, или использованием -cp
со всеми необходимыми jar-файлами + имя основного класса.
Поскольку вы не возитесь с манифестами jar, вы не создаете исполняемый jar, поэтому вам следует придерживаться опции -cp
. Вам необходимо указать все необходимые jar-файлы в опции -cp
(разделенные :
в Linux или Mac и ;
в Windows), а также имя основного класса в конце команды:
java -cp "hello.jar;main.jar" MainKt
Имя основного класса MainKt
получается из имени файла, содержащего вашу функцию main()
, и имени пакета внутри файла, как определено (хотя и неявно) в документации Kotlin.
Вы также можете проверить этот ответ для получения более подробной информации.
Хотя знать, как работает компилятор, полезно, но практически никто не вызывает
kotlinc
(илиjavac
) вручную. Все будут использовать IDE. Некоторые из ведущих IDE поддерживают Kotlin и могут использоваться бесплатно. Получите один из них, и вы легко «шпионите» за тем, как IDE будет запускать ваш код... он формирует командуjava
, правильно устанавливающую путь к классу (-cp
) и т. д. Я думаю, что это предоставит вам кратчайший путь к получению рабочего примера, который вы затем сможете вернуться в командную строку для использования.