JVM, компиляция и запуск программы
Разбираемся, что происходит между написанным кодом и его выполнением.
JVM (Java Virtual Machine) — виртуальная машина, исполняющая байт-код; именно на ней по умолчанию работают программы на Kotlin.
Чтобы уверенно писать на Kotlin, полезно понимать путь от исходного файла до запущенной программы. Это снимает много вопросов: почему нужен JDK, что такое .class и почему один и тот же код работает на Windows, macOS и Linux одинаково.
Путь от исходника к запуску
Жизненный цикл программы можно изобразить так:
Main.kt ──компиляция──▶ байт-код (.class / .jar) ──▶ JVM ──▶ результат
(исходник) kotlinc javaСначала компилятор kotlinc читает ваш .kt-файл и превращает его в байт-код. Затем виртуальная машина (команда java) загружает этот байт-код и исполняет его. JVM устанавливается под конкретную операционную систему, а байт-код один на всех — поэтому Kotlin «пишется один раз, запускается везде».
Что нужно установить
Для запуска Kotlin на компьютере понадобятся JDK (Java Development Kit, в нём есть JVM) и компилятор Kotlin. Чаще всего разработчики используют среду IntelliJ IDEA, где всё уже настроено. Команды в консоли выглядят так:
# Скомпилировать в исполняемый jar
kotlinc Main.kt -include-runtime -d app.jar
# Запустить
java -jar app.jarФайлы и функции верхнего уровня
В Kotlin функции и переменные можно объявлять прямо в файле, без класса. Это называется функции верхнего уровня.
// файл Main.kt
fun greet(name: String): String {
return "Привет, $name"
}
fun main() {
println(greet("мир"))
}Вывод:
Привет, мир
Как работает под капотом
Хотя вы пишете функцию верхнего уровня, для JVM любой код обязан жить внутри класса. Поэтому компилятор Kotlin незаметно создаёт класс-обёртку: файл Main.kt с функцией main превращается в класс MainKt с методом main. Имя класса — это имя файла плюс суффикс Kt. Понимать это полезно, когда Kotlin-код вызывают из Java.
Частые ошибки
- Путать JDK и JRE. Для разработки нужен JDK (в нём есть компилятор), JRE предназначен только для запуска.
- Забыть флаг
-include-runtime. Без него в jar не попадёт стандартная библиотека Kotlin, и запуск упадёт. - Ждать «нативный» exe. По умолчанию Kotlin даёт байт-код для JVM, а не машинный код (для нативной сборки есть отдельный Kotlin/Native).
Итог
- Исходник
.ktкомпилируется в байт-код, который исполняет JVM. - Байт-код переносим между ОС — отсюда кроссплатформенность.
- Функции можно объявлять на верхнем уровне файла, без класса.
- Компилятор всё равно оборачивает их в класс вида
ИмяФайлаKt.