Spec-Zone.ru › Kotlin 2

Что нового в Kotlin 2.2.0

Выпущено: 23 июня 2025 г.

Вышел Kotlin 2.2.0! Вот основные нововведения:

  • Язык: новые возможности языка в предварительной версии, включая контекстные параметры. Несколько ранее экспериментальных возможностей теперь имеют статус стабильных, например условия-стражи, нелокальные break и continue, а также интерполяция с несколькими знаками доллара.

  • Компилятор Kotlin: унифицированное управление предупреждениями компилятора.

  • Kotlin/JVM: изменения в генерации методов по умолчанию для функций интерфейсов.

  • Kotlin/Native: LLVM 19 и новые возможности отслеживания и регулирования потребления памяти.

  • Kotlin/Wasm: отдельная цель Wasm и возможность настраивать Binaryen для каждого проекта.

  • Kotlin/JS: исправление для метода copy(), генерируемого для интерфейсов @JsPlainObject.

  • Gradle: проверка бинарной совместимости в плагине Kotlin Gradle.

  • Стандартная библиотека: стабильные API Base64 и HexFormat.

  • Документация: в документацию Kotlin внесены важные улучшения.

Вы также можете посмотреть видео, в котором команда по развитию языка Kotlin обсуждает новые возможности и отвечает на вопросы:

Информацию о цикле выпуска Kotlin см. в разделе Процесс выпуска Kotlin.

Поддержка IDE

Плагины Kotlin с поддержкой версии 2.2.0 входят в состав последних версий IntelliJ IDEA и Android Studio. Обновлять плагин Kotlin в IDE не нужно. Достаточно изменить версию Kotlin на 2.2.0 в скриптах сборки.

Подробнее см. в разделе Обновление до новой версии.

Язык

В этом выпуске условия-стражи, нелокальные break и continue, а также интерполяция с несколькими знаками доллара получили статус стабильных. Кроме того, в предварительной версии представлены такие возможности, как контекстные параметры и контекстно-зависимое разрешение.

Предварительная версия контекстных параметров

Контекстные параметры позволяют функциям и свойствам объявлять зависимости, неявно доступные в окружающем контексте.

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

Контекстные параметры заменяют старую экспериментальную возможность, называвшуюся контекстными получателями. Чтобы перейти с контекстных получателей на контекстные параметры, воспользуйтесь специальной поддержкой в IntelliJ IDEA, описанной в публикации в блоге.

Основное отличие заключается в том, что контекстные параметры не вводятся как получатели в теле функции. Поэтому для доступа к их членам нужно использовать имена контекстных параметров, в отличие от контекстных получателей, чей контекст доступен неявно.

Контекстные параметры в Kotlin значительно упрощают управление зависимостями благодаря упрощённому внедрению зависимостей, улучшенному проектированию DSL и операциям с областью действия. Подробнее см. в KEEP, посвящённом этой возможности.

Как объявить контекстные параметры

Контекстные параметры для свойств и функций можно объявлять с помощью ключевого слова context, за которым следует список параметров; каждый параметр имеет вид name: Type. Вот пример зависимости от интерфейса UserService:

// UserService defines the dependency required in the context 
interface UserService {
    fun log(message: String)
    fun findUserById(id: Int): String
}

// Declares a function with a context parameter
context(users: UserService)
fun outputMessage(message: String) {
    // Uses log from the context
    users.log("Log: $message")
}

// Declares a property with a context parameter
context(users: UserService)
val firstUser: String
    // Uses findUserById from the context    
    get() = users.findUserById(1)

В качестве имени контекстного параметра можно использовать _. В этом случае значение параметра доступно для разрешения, но к нему нельзя обратиться по имени внутри блока:

// Uses "_" as context parameter name
context(_: UserService)
fun logWelcome() {
    // Finds the appropriate log function from UserService
    outputMessage("Welcome!")
}

Как включить контекстные параметры

Чтобы включить контекстные параметры в проекте, используйте следующий параметр компилятора в командной строке:

-Xcontext-parameters

Или добавьте его в блок compilerOptions {} файла сборки Gradle:

// build.gradle.kts
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xcontext-parameters")
    }
}

Одновременное указание параметров компилятора -Xcontext-receivers и -Xcontext-parameters приводит к ошибке.

Оставьте отзыв

Эту возможность планируется стабилизировать и улучшить в будущих выпусках Kotlin. Мы будем благодарны за ваши отзывы в нашем трекере задач YouTrack.

Предварительная версия контекстно-зависимого разрешения

В Kotlin 2.2.0 представлена предварительная реализация контекстно-зависимого разрешения.

Обзор этой возможности можно посмотреть в видео:

Ранее требовалось указывать полные имена элементов перечисления или членов запечатанного класса, даже если тип можно было вывести из контекста. Например:

enum class Problem {
    CONNECTION, AUTHENTICATION, DATABASE, UNKNOWN
}

fun message(problem: Problem): String = when (problem) {
    Problem.CONNECTION -> "connection"
    Problem.AUTHENTICATION -> "authentication"
    Problem.DATABASE -> "database"
    Problem.UNKNOWN -> "unknown"
}

Теперь благодаря контекстно-зависимому разрешению можно опускать имя типа в тех контекстах, где ожидаемый тип известен:

enum class Problem {
    CONNECTION, AUTHENTICATION, DATABASE, UNKNOWN
}

// Resolves enum entries based on the known type of problem
fun message(problem: Problem): String = when (problem) {
    CONNECTION -> "connection"
    AUTHENTICATION -> "authentication"
    DATABASE -> "database"
    UNKNOWN -> "unknown"
}

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

  • Тема выражения when

  • Явно указанный тип возвращаемого значения

  • Объявленный тип переменной

  • Проверки типа (is) и приведения типов (as)

  • Известный тип иерархии запечатанных классов

  • Объявленный тип параметра

Контекстно-зависимое разрешение не применяется к функциям, свойствам с параметрами и свойствам-расширениям с получателями.

Чтобы опробовать контекстно-зависимое разрешение в проекте, используйте следующий параметр компилятора в командной строке:

-Xcontext-sensitive-resolution

Или добавьте его в блок compilerOptions {} файла сборки Gradle:

// build.gradle.kts
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xcontext-sensitive-resolution")
    }
}

Мы планируем стабилизировать и улучшить эту возможность в будущих выпусках Kotlin и будем благодарны за ваши отзывы в нашем трекере задач YouTrack.

Предварительная версия возможностей для use-site-целей аннотаций

В Kotlin 2.2.0 представлены две возможности, упрощающие работу с use-site-целями аннотаций.

@all — метацель для свойств

В Kotlin можно прикреплять аннотации к отдельным частям объявления, известным как use-site-цели. Однако аннотирование каждой цели по отдельности было сложным и чреватым ошибками:

data class User(
    val username: String,

    @param:Email      // Constructor parameter
    @field:Email      // Backing field
    @get:Email        // Getter method
    @property:Email   // Kotlin property reference
    val email: String,
) {
    @field:Email
    @get:Email
    @property:Email
    val secondaryEmail: String? = null
}

Чтобы упростить эту задачу, в Kotlin добавлена новая метацель @all для свойств. С её помощью компилятор применяет аннотацию ко всем подходящим частям свойства. При использовании этой метацели @all пытается применить аннотацию к следующим элементам:

  • param: параметру конструктора, если он объявлен в первичном конструкторе.

  • property: самому свойству Kotlin.

  • field: резервному полю, если оно существует.

  • get: методу-геттеру.

  • setparam: параметру метода-сеттера, если свойство объявлено как var.

  • RECORD_COMPONENT: если класс является @JvmRecord, аннотация применяется к компоненту записи Java. Это поведение повторяет способ обработки аннотаций компонентов записей в Java.

Компилятор применяет аннотацию только к целям, подходящим для данного свойства.

В приведённом ниже примере аннотация @Email применяется ко всем подходящим целям каждого свойства:

data class User(
    val username: String,

    // Applies @Email to param, property, field,
    // get, and setparam (if var)
    @all:Email val email: String,
) {
    // Applies @Email to property, field, and get
    // (no param since it's not in the constructor)
    @all:Email val secondaryEmail: String? = null
}

Метацель @all можно использовать с любым свойством — как внутри первичного конструктора, так и вне его. Однако метацель @all нельзя использовать с несколькими аннотациями.

Эта новая возможность упрощает синтаксис, обеспечивает единообразие и улучшает взаимодействие с записями Java.

Чтобы включить метацель @all в проекте, используйте следующий параметр компилятора в командной строке:

-Xannotation-target-all

Или добавьте его в блок compilerOptions {} файла сборки Gradle:

// build.gradle.kts
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xannotation-target-all")
    }
}

Эта возможность находится в предварительной версии. Сообщайте о проблемах в нашем трекере задач YouTrack. Дополнительную информацию о метацели @all см. в предложении KEEP.

Новые правила выбора use-site-целей аннотаций по умолчанию

В Kotlin 2.2.0 представлены новые правила выбора целей для распространения аннотаций на параметры, поля и свойства. Ранее аннотация по умолчанию применялась только к одной из целей param, property или field; теперь правила выбора лучше соответствуют ожидаемому поведению аннотаций.

Если подходят несколько целей, одна или несколько из них выбираются следующим образом:

  • Если подходит цель параметра конструктора (param), используется она.

  • Если подходит цель свойства (property), используется она.

  • Если подходит цель поля (field), а property не подходит, используется field.

Если подходит несколько целей, но ни одна из целей param, property или field не подходит, возникает ошибка аннотации.

Чтобы включить эту возможность, добавьте её в блок compilerOptions {} файла сборки Gradle:

// build.gradle.kts
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xannotation-default-target=param-property")
    }
}

Или используйте аргумент командной строки для компилятора:

-Xannotation-default-target=param-property

Чтобы использовать прежнее поведение, можно:

  • В отдельном случае явно указать нужную цель, например использовать @param:Annotation вместо @Annotation.

  • Для всего проекта использовать этот флаг в файле сборки Gradle:

    // build.gradle.kts
    kotlin {
        compilerOptions {
            freeCompilerArgs.add("-Xannotation-default-target=first-only")
        }
    }
    

Эта возможность находится в предварительной версии. Сообщайте о проблемах в нашем трекере задач YouTrack. Дополнительную информацию о новых правилах выбора use-site-целей аннотаций по умолчанию см. в предложении KEEP.

Поддержка вложенных псевдонимов типов

В Kotlin 2.2.0 добавлена поддержка объявления псевдонимов типов внутри других объявлений.

Обзор этой возможности можно посмотреть в видео:

Ранее псевдонимы типов можно было объявлять только на верхнем уровне файла Kotlin. Это означало, что даже внутренние или предметно-ориентированные псевдонимы типов приходилось размещать вне класса, в котором они использовались.

Начиная с версии 2.2.0, псевдонимы типов можно объявлять внутри других объявлений, если они не захватывают параметры типа внешнего класса:

class Dijkstra {
    typealias VisitedNodes = Set<Node>

    private fun step(visited: VisitedNodes, ...) = ...
}

Для вложенных псевдонимов типов действуют дополнительные ограничения, например в них нельзя указывать параметры типа. Полный список правил см. в документации.

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

Как включить вложенные псевдонимы типов

Чтобы включить вложенные псевдонимы типов в проекте, используйте следующий параметр компилятора в командной строке:

-Xnested-type-aliases

Или добавьте его в блок compilerOptions {} файла сборки Gradle:

// build.gradle.kts
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xnested-type-aliases")
    }
}

Поделитесь отзывом

Вложенные псевдонимы типов сейчас находятся в статусе бета-версии. Сообщайте о проблемах в нашем трекере задач YouTrack. Дополнительную информацию об этой возможности см. в предложении KEEP.

Стабильные возможности: условия-стражи, нелокальные break и continue, а также интерполяция с несколькими знаками доллара

В Kotlin 2.1.0 несколько новых возможностей языка были представлены в предварительной версии. Мы рады сообщить, что в этом выпуске следующие возможности языка получили стабильный статус:

  • Условия-стражи в when с темой

  • Нелокальные break и continue

  • Интерполяция с несколькими знаками доллара: улучшенная обработка $ в строковых литералах

Полный список предложений и возможностей, связанных с проектированием языка Kotlin.

Компилятор Kotlin: унифицированное управление предупреждениями компилятора

В Kotlin 2.2.0 добавлен новый параметр компилятора -Xwarning-level. Он обеспечивает единый способ управления предупреждениями компилятора в проектах Kotlin.

Ранее можно было задавать только общие правила для всего модуля: например, отключить все предупреждения с помощью -nowarn, превращать все предупреждения в ошибки компиляции с помощью -Werror или включить дополнительные проверки компилятора с помощью -Wextra. Единственным способом настроить отдельные предупреждения был параметр -Xsuppress-warning.

С новым решением можно единообразно переопределять общие правила и исключать отдельные диагностические сообщения.

Как использовать

Новый параметр компилятора имеет следующий синтаксис:

-Xwarning-level=DIAGNOSTIC_NAME:(error|warning|disabled)
  • error: превращает указанное предупреждение в ошибку.

  • warning: выдаёт предупреждение; этот режим включён по умолчанию.

  • disabled: полностью отключает указанное предупреждение для всего модуля.

Обратите внимание: новый параметр компилятора позволяет настраивать только уровень серьёзности предупреждений.

Примеры использования

Новое решение позволяет точнее настраивать выдачу предупреждений в проекте, сочетая общие правила с отдельными. Выберите нужный сценарий:

Подавление предупреждений

Команда

Описание

-nowarn

Подавляет все предупреждения во время компиляции.

-Xwarning-level=DIAGNOSTIC_NAME:disabled

Подавляет только указанные предупреждения.

-nowarn -Xwarning-level=DIAGNOSTIC_NAME:warning

Подавляет все предупреждения, кроме указанных.

Преобразование предупреждений в ошибки

Команда

Описание

-Werror

Преобразует все предупреждения в ошибки компиляции.

-Xwarning-level=DIAGNOSTIC_NAME:error

Преобразует в ошибки только указанные предупреждения.

-Werror -Xwarning-level=DIAGNOSTIC_NAME:warning

Преобразует в ошибки все предупреждения, кроме указанных.

Включение дополнительных предупреждений компилятора

Команда

Описание

-Wextra

Включает все дополнительные проверки объявлений, выражений и типов, при истинном значении которых выдаются предупреждения.

-Xwarning-level=DIAGNOSTIC_NAME:warning

Включает только указанные дополнительные проверки компилятора.

-Wextra -Xwarning-level=DIAGNOSTIC_NAME:disabled

Включает все дополнительные проверки, кроме указанных.

Списки предупреждений

Если нужно исключить из общих правил много предупреждений, их можно перечислить в отдельном файле с помощью @argfile.

Оставьте отзыв

Новый параметр компилятора пока имеет статус экспериментального. Сообщайте о проблемах в нашем трекере задач YouTrack.

Kotlin/JVM

Kotlin 2.2.0 содержит множество обновлений для JVM. Теперь компилятор поддерживает байткод Java 24 и изменяет генерацию методов по умолчанию для функций интерфейсов. В этом выпуске также упрощена работа с аннотациями в метаданных Kotlin, улучшена совместимость Java с inline-классами-значениями и расширена поддержка аннотирования записей JVM.

Изменения в генерации методов по умолчанию для функций интерфейсов

Начиная с Kotlin 2.2.0 функции, объявленные в интерфейсах, компилируются в методы JVM по умолчанию, если не заданы другие настройки. Это изменение влияет на компиляцию функций интерфейсов Kotlin с реализациями в байткод.

Это поведение контролируется новым стабильным параметром компилятора -jvm-default, который заменяет устаревший параметр -Xjvm-default.

Управлять поведением параметра -jvm-default можно с помощью следующих значений:

  • enable (по умолчанию): генерирует реализации по умолчанию в интерфейсах и включает функции-мосты в подклассы и классы DefaultImpls. Используйте этот режим для сохранения бинарной совместимости с более ранними версиями Kotlin.

  • no-compatibility: генерирует только реализации по умолчанию в интерфейсах. В этом режиме пропускаются мосты совместимости и классы DefaultImpls, что делает его подходящим для нового кода.

  • disable: отключает реализации по умолчанию в интерфейсах. Генерируются только функции-мосты и классы DefaultImpls, что соответствует поведению до Kotlin 2.2.0.

Чтобы настроить параметр компилятора -jvm-default, задайте свойство jvmDefault в Gradle Kotlin DSL:

// build.gradle.kts
kotlin {
    compilerOptions {
        jvmDefault = JvmDefaultMode.NO_COMPATIBILITY
    }
}

Поддержка чтения и записи аннотаций в метаданных Kotlin

Раньше для чтения аннотаций из скомпилированных файлов классов JVM приходилось использовать рефлексию или анализ байткода, а затем вручную сопоставлять их с записями метаданных на основе сигнатур. Этот процесс был подвержен ошибкам, особенно для перегруженных функций.

Теперь в Kotlin 2.2.0 библиотека Kotlin Metadata JVM поддерживает чтение аннотаций, хранящихся в метаданных Kotlin.

Чтобы аннотации были доступны в метаданных скомпилированных файлов, добавьте следующий параметр компилятора:

-Xannotations-in-metadata

Также его можно добавить в блок compilerOptions {} файла сборки Gradle:

// build.gradle.kts
kotlin {
    compilerOptions {
        freeCompilerArgs.add("-Xannotations-in-metadata")
    }
}

Если этот параметр включен, компилятор Kotlin записывает аннотации в метаданные вместе с байткодом JVM, делая их доступными для библиотеки kotlin-metadata-jvm.

Библиотека предоставляет следующие API для доступа к аннотациям:

  • KmClass.annotations

  • KmFunction.annotations

  • KmProperty.annotations

  • KmConstructor.annotations

  • KmPropertyAccessorAttributes.annotations

  • KmValueParameter.annotations

  • KmFunction.extensionReceiverAnnotations

  • KmProperty.extensionReceiverAnnotations

  • KmProperty.backingFieldAnnotations

  • KmProperty.delegateFieldAnnotations

  • KmEnumEntry.annotations

Эти API являются экспериментальными. Чтобы включить их, используйте аннотацию @OptIn(ExperimentalAnnotationsInMetadata::class).

Пример чтения аннотаций из метаданных Kotlin:

@file:OptIn(ExperimentalAnnotationsInMetadata::class)

import kotlin.metadata.ExperimentalAnnotationsInMetadata
import kotlin.metadata.jvm.KotlinClassMetadata

annotation class Label(val value: String)

@Label("Message class")
class Message

fun main() {
    val metadata = Message::class.java.getAnnotation(Metadata::class.java)
    val kmClass = (KotlinClassMetadata.readStrict(metadata) as KotlinClassMetadata.Class).kmClass
    println(kmClass.annotations)
    // [@Label(value = StringValue("Message class"))]
}

Если вы используете библиотеку kotlin-metadata-jvm в своих проектах, рекомендуем протестировать и обновить код для поддержки аннотаций. В противном случае, когда аннотации в метаданных станут включены по умолчанию в будущей версии Kotlin, проекты могут создавать недопустимые или неполные метаданные.

Если у вас возникнут проблемы, сообщите о них в наш трекер задач.

Улучшенная совместимость с Java для inline-классов-значений

В Kotlin 2.2.0 появилась новая экспериментальная аннотация: @JvmExposeBoxed. Эта аннотация упрощает использование inline-классов-значений из Java.

Обзор этой функции представлен в видео:

По умолчанию Kotlin компилирует inline-классы-значения в неупакованном представлении. Оно обеспечивает более высокую производительность, но часто затрудняет или даже делает невозможным использование классов из Java. Например:

@JvmInline value class PositiveInt(val number: Int) {
    init { require(number >= 0) }
}

В этом случае класс не упакован, поэтому в Java нет доступного конструктора для вызова. Также из Java нельзя запустить блок init, чтобы убедиться, что значение number положительное.

Если аннотировать класс с помощью @JvmExposeBoxed, Kotlin сгенерирует открытый конструктор, который можно напрямую вызвать из Java, и блок init также будет выполнен.

Аннотацию @JvmExposeBoxed можно применять на уровне класса, конструктора или функции, чтобы точно контролировать, что будет доступно из Java.

Например, в следующем коде функция расширения .timesTwoBoxed() недоступна из Java:

@JvmInline
value class MyInt(val value: Int)

fun MyInt.timesTwoBoxed(): MyInt = MyInt(this.value * 2)

Чтобы можно было создать экземпляр класса MyInt и вызвать функцию .timesTwoBoxed() из кода Java, добавьте аннотацию @JvmExposeBoxed и к классу, и к функции:

@JvmExposeBoxed
@JvmInline
value class MyInt(val value: Int)

@JvmExposeBoxed
fun MyInt.timesTwoBoxed(): MyInt = MyInt(this.value * 2)

С такими аннотациями компилятор Kotlin генерирует доступный из Java конструктор для класса MyInt. Он также генерирует перегрузку функции расширения, использующую упакованное представление класса-значения. В результате следующий код Java выполняется успешно:

MyInt input = new MyInt(5);
MyInt output = ExampleKt.timesTwoBoxed(input);

Если вы не хотите аннотировать каждую часть inline-классов-значений, которую нужно сделать доступной, можно применить аннотацию ко всему модулю. Чтобы включить такое поведение для модуля, скомпилируйте его с параметром -Xjvm-expose-boxed. Компиляция с этим параметром равносильна добавлению аннотации @JvmExposeBoxed к каждому объявлению модуля.

Эта новая аннотация не меняет способ внутренней компиляции и использования классов-значений в Kotlin, и весь существующий скомпилированный код остается действительным. Она лишь добавляет новые возможности для улучшения совместимости с Java. Производительность кода Kotlin, использующего классы-значения, не меняется.

Аннотация @JvmExposeBoxed полезна авторам библиотек, которым нужно предоставлять упакованные варианты функций-членов и получать упакованные типы возвращаемых значений. Она избавляет от необходимости выбирать между inline-классом-значением (эффективным, но доступным только в Kotlin) и data-классом (совместимым с Java, но всегда упакованным).

Подробное объяснение работы аннотации @JvmExposedBoxed и решаемых ею проблем см. в предложении KEEP.

Улучшенная поддержка аннотирования записей JVM

Kotlin поддерживает записи JVM начиная с Kotlin 1.5.0. Теперь в Kotlin 2.2.0 улучшена обработка аннотаций компонентов записей, особенно в отношении цели Java RECORD_COMPONENT.

Во-первых, если вы хотите использовать RECORD_COMPONENT в качестве цели аннотации, необходимо вручную добавить аннотации для Kotlin (@Target) и Java. Это связано с тем, что аннотация @Target в Kotlin не поддерживает RECORD_COMPONENT. Например:

@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
@java.lang.annotation.Target(ElementType.CLASS, ElementType.RECORD_COMPONENT)
annotation class exampleClass

Поддерживать оба списка вручную может быть непросто, поэтому в Kotlin 2.2.0 добавлено предупреждение компилятора, если цели Kotlin и Java не совпадают. Например, если в списке целей Java пропустить ElementType.CLASS, компилятор сообщит:

Incompatible annotation targets: Java target 'CLASS' missing, corresponding to Kotlin targets 'CLASS'.

Во-вторых, поведение Kotlin отличается от Java при распространении аннотаций в записях. В Java аннотации компонента записи автоматически применяются к резервному полю, геттеру и параметру конструктора. По умолчанию Kotlin этого не делает, но теперь такое поведение можно воспроизвести с помощью цели применения @all:.

Например:

@JvmRecord
data class Person(val name: String, @all:Positive val age: Int)

При использовании @JvmRecord с @all: Kotlin теперь:

  • Распространяет аннотацию на свойство, резервное поле, параметр конструктора и геттер.

  • Также применяет аннотацию к компоненту записи, если аннотация поддерживает цель Java RECORD_COMPONENT.

Kotlin/Native

Начиная с версии 2.2.0 Kotlin/Native использует LLVM 19. В этом выпуске также появились экспериментальные функции для отслеживания и настройки потребления памяти.

Выделение памяти для каждого объекта

Аллокатор памяти Kotlin/Native теперь может резервировать память для каждого объекта отдельно. В некоторых случаях это может помочь соблюсти строгие ограничения памяти или снизить потребление памяти при запуске приложения.

Эта новая функция предназначена для замены параметра компилятора -Xallocator=std, который включал системный аллокатор памяти вместо стандартного. Теперь можно отключить буферизацию (постраничное выделение памяти), не переключая аллокаторы памяти.

В настоящее время функция экспериментальная. Чтобы включить ее, задайте следующий параметр в файле gradle.properties:

kotlin.native.binary.pagedAllocator=false

Сообщайте о любых проблемах в наш трекер задач YouTrack.

Поддержка строк в кодировке Latin-1 во время выполнения

Теперь Kotlin поддерживает строки в кодировке Latin-1, как и JVM. Это должно помочь уменьшить размер двоичных файлов приложения и оптимизировать потребление памяти.

По умолчанию строки в Kotlin хранятся в кодировке UTF-16, где каждый символ занимает два байта. В некоторых случаях из-за этого строки занимают в двоичном файле вдвое больше места, чем в исходном коде, а чтение данных из простого файла ASCII может потребовать вдвое больше памяти, чем занимает сам файл на диске.

Кодировка Latin-1 (ISO 8859-1), в свою очередь, представляет каждый из первых 256 символов Unicode всего одним байтом. Если поддержка Latin-1 включена, строки хранятся в этой кодировке, пока все символы входят в ее диапазон. В противном случае используется кодировка UTF-16 по умолчанию.

Как включить поддержку Latin-1

В настоящее время функция экспериментальная. Чтобы включить ее, задайте следующий параметр в файле gradle.properties:

kotlin.native.binary.latin1Strings=true

Известные проблемы

Пока функция остается экспериментальной, функции расширения cinterop String.pin, String.usePinned и String.refTo работают менее эффективно. Каждый вызов может запускать автоматическое преобразование строки в UTF-16.

Команда Kotlin выражает особую благодарность коллегам из Google и в особенности Соне Вальчук за реализацию этой функции.

Дополнительные сведения о потреблении памяти в Kotlin см. в документации.

Улучшенное отслеживание потребления памяти на платформах Apple

Начиная с Kotlin 2.2.0 память, выделенная кодом Kotlin, помечается тегами. Это может помочь при отладке проблем с памятью на платформах Apple.

При изучении высокого потребления памяти приложением теперь можно определить, сколько памяти зарезервировано кодом Kotlin. Память, используемая Kotlin, помечена идентификатором, и ее можно отслеживать с помощью таких инструментов, как VM Tracker в Xcode Instruments.

Эта функция включена по умолчанию, но доступна только в стандартном аллокаторе памяти Kotlin/Native, если выполнены все следующие условия:

  • Маркировка включена. Память должна быть помечена допустимым идентификатором. Apple рекомендует числа от 240 до 255; значение по умолчанию — 246.

    Если задать свойство Gradle kotlin.native.binary.mmapTag=0, маркировка будет отключена.

  • Выделение с помощью mmap. Аллокатор должен использовать системный вызов mmap для отображения файлов в память.

    Если задать свойство Gradle kotlin.native.binary.disableMmap=true, стандартный аллокатор будет использовать malloc вместо mmap.

  • Постраничное выделение включено. Постраничное выделение памяти (буферизация) должно быть включено.

    Если задать свойство Gradle kotlin.native.binary.pagedAllocator=false, память вместо этого будет резервироваться для каждого объекта отдельно.

Дополнительные сведения о потреблении памяти в Kotlin см. в документации.

Обновление LLVM с версии 16 до 19

В Kotlin 2.2.0 мы обновили LLVM с версии 16 до версии 19. Новая версия содержит улучшения производительности, исправления ошибок и обновления безопасности.

Это обновление не должно повлиять на ваш код, но если вы столкнетесь с проблемами, сообщите о них в наш трекер задач.

Поддержка Windows 7 объявлена устаревшей

Начиная с Kotlin 2.2.0 минимальная поддерживаемая версия Windows повышена с Windows 7 до Windows 10. Поскольку Microsoft прекратила поддержку Windows 7 в январе 2025 года, мы также решили объявить эту устаревшую целевую платформу устаревшей.

Дополнительные сведения см. в разделе Поддерживаемые целевые платформы и хосты Kotlin/Native.

Kotlin/Wasm

В этом выпуске инфраструктура сборки целевой платформы Wasm отделена от целевой платформы JavaScript. Кроме того, теперь можно настраивать инструмент Binaryen для каждого проекта или модуля.

Инфраструктура сборки Wasm отделена от инфраструктуры JavaScript

Раньше целевая платформа wasmJs использовала ту же инфраструктуру, что и целевая платформа js. В результате обе платформы находились в одном каталоге (build/js) и использовали одни и те же задачи и конфигурации NPM.

Теперь целевая платформа wasmJs имеет собственную инфраструктуру, отдельную от целевой платформы js. Благодаря этому задачи и типы Wasm отличаются от задач и типов JavaScript и могут настраиваться независимо.

Кроме того, файлы проектов, связанные с Wasm, и зависимости NPM теперь хранятся в отдельном каталоге build/wasm.

Для Wasm добавлены новые задачи, связанные с NPM, а существующие задачи JavaScript теперь предназначены только для JavaScript:

Задачи Wasm

Задачи JavaScript

kotlinWasmNpmInstall

kotlinNpmInstall

wasmRootPackageJson

rootPackageJson

Аналогичным образом добавлены новые объявления, специфичные для Wasm:

Объявления Wasm

Объявления JavaScript

WasmNodeJsRootPlugin

NodeJsRootPlugin

WasmNodeJsPlugin

NodeJsPlugin

WasmYarnPlugin

YarnPlugin

WasmNodeJsRootExtension

NodeJsRootExtension

WasmNodeJsEnvSpec

NodeJsEnvSpec

WasmYarnRootEnvSpec

YarnRootEnvSpec

Теперь можно работать с целевой платформой Wasm независимо от целевой платформы JavaScript, что упрощает процесс настройки.

Это изменение включено по умолчанию и не требует дополнительной настройки.

Настройка Binaryen для каждого проекта

Ранее инструмент Binaryen, используемый в Kotlin/Wasm для оптимизации production-сборок, настраивался один раз в корневом проекте.

Теперь инструмент Binaryen можно настраивать для каждого проекта или модуля. Это соответствует рекомендациям по использованию Gradle и обеспечивает лучшую поддержку таких возможностей, как изоляция проектов, повышая производительность и надежность сборки сложных проектов.

Кроме того, при необходимости теперь можно задавать разные версии Binaryen для разных модулей.

Эта функция включена по умолчанию. Однако, если вы используете собственную конфигурацию Binaryen, теперь ее нужно применять для каждого проекта, а не только в корневом проекте.

Kotlin/JS

В этом выпуске улучшены функция copy() в интерфейсах @JsPlainObject, псевдонимы типов в файлах с аннотацией @JsModule и другие возможности Kotlin/JS.

Исправление для copy() в интерфейсах @JsPlainObject

В Kotlin/JS есть экспериментальный плагин js-plain-objects, добавляющий функцию copy() для интерфейсов с аннотацией @JsPlainObject. Функцию copy() можно использовать для обработки объектов.

Однако первоначальная реализация copy() была несовместима с наследованием, что вызывало проблемы, если интерфейс @JsPlainObject наследовал другие интерфейсы.

Чтобы избежать ограничений для простых объектов, функция copy() перемещена с самого объекта в его объект-компаньон:

@JsPlainObject
external interface User {
    val name: String
    val age: Int
}

fun main() {
    val user = User(name = "SomeUser", age = 21)
    // This syntax is not valid anymore
    val copy = user.copy(age = 35)      
    // This is the correct syntax
    val copy = User.copy(user, age = 35)
}

Это изменение устраняет конфликты в иерархии наследования и неоднозначность. Начиная с Kotlin 2.2.0 оно включено по умолчанию.

Поддержка псевдонимов типов в файлах с аннотацией @JsModule

Ранее файлы с аннотацией @JsModule, предназначенные для импорта объявлений из модулей JavaScript, могли содержать только внешние объявления. Это означало, что в таких файлах нельзя было объявить typealias.

Начиная с Kotlin 2.2.0 в файлах, помеченных @JsModule, можно объявлять псевдонимы типов:

@file:JsModule("somepackage")
package somepackage
typealias SomeClass = Any

Это изменение устраняет одно из ограничений совместимости Kotlin/JS, а в будущих выпусках планируются дальнейшие улучшения.

Поддержка псевдонимов типов в файлах с @JsModule включена по умолчанию.

Поддержка @JsExport в мультиплатформенных объявлениях expect

При работе с механизмом expect/actual в проектах Kotlin Multiplatform было невозможно использовать аннотацию @JsExport для объявлений expect в общем коде.

Начиная с этого выпуска аннотацию @JsExport можно применять непосредственно к объявлениям expect:

// commonMain

// Produced error, but now works correctly 
@JsExport
expect class WindowManager {
    fun close()
}

@JsExport
fun acceptWindowManager(manager: WindowManager) {
    ...
}

// jsMain

@JsExport
actual class WindowManager {
    fun close() {
        window.close()
    }
}

Также необходимо добавить аннотацию @JsExport к соответствующей реализации actual в исходном наборе JavaScript, используя только типы, доступные для экспорта.

Это исправление позволяет корректно экспортировать в JavaScript общий код, определенный в commonMain. Теперь мультиплатформенный код можно предоставлять потребителям JavaScript без ручных обходных решений.

Это изменение включено по умолчанию.

Возможность использовать @JsExport с типом Promise<Unit>

Ранее при попытке экспортировать функцию, возвращающую тип Promise<Unit>, с аннотацией @JsExport компилятор Kotlin выдавал ошибку.

Типы возвращаемых значений вроде Promise<Int> работали корректно, но при использовании Promise<Unit> появлялось предупреждение «тип нельзя экспортировать», хотя в TypeScript этот тип корректно сопоставлялся с Promise<void>.

Это ограничение снято. Теперь следующий код компилируется без ошибок:

// Worked correctly before
@JsExport
fun fooInt(): Promise<Int> = GlobalScope.promise {
    delay(100)
    return@promise 42
}

// Produced error, but now works correctly
@JsExport
fun fooUnit(): Promise<Unit> = GlobalScope.promise {
    delay(100)
}

Это изменение снимает ненужное ограничение модели взаимодействия Kotlin/JS. Исправление включено по умолчанию.

Gradle

Kotlin 2.2.0 полностью совместим с Gradle версий от 7.6.3 до 8.14. Также можно использовать версии Gradle вплоть до последней. Однако имейте в виду, что это может привести к предупреждениям об устаревших элементах, а некоторые новые функции Gradle могут не работать.

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

Проверка бинарной совместимости в плагине Kotlin Gradle

Чтобы упростить проверку бинарной совместимости между версиями библиотеки, мы экспериментируем с переносом функциональности средства проверки бинарной совместимости в плагин Kotlin Gradle (KGP). Вы можете попробовать его в тестовых проектах, но пока мы не рекомендуем использовать его в production.

В ходе этого экспериментального этапа поддержка исходного средства проверки бинарной совместимости продолжается.

Библиотеки Kotlin могут использовать один из двух бинарных форматов: файлы классов JVM или klib. Поскольку эти форматы несовместимы, KGP работает с каждым из них отдельно.

Чтобы включить набор функций проверки бинарной совместимости, добавьте следующий код в блок kotlin{} файла build.gradle.kts:

// build.gradle.kts
kotlin {
    @OptIn(org.jetbrains.kotlin.gradle.dsl.abi.ExperimentalAbiValidation::class)
    abiValidation {
        // Use the set() function to ensure compatibility with older Gradle versions
        enabled.set(true)
    }
}

Если в проекте есть несколько модулей, для которых нужно проверять бинарную совместимость, настройте эту функцию отдельно для каждого модуля. Для каждого модуля можно задать собственную конфигурацию.

После включения функции запустите задачу Gradle checkLegacyAbi, чтобы проверить наличие проблем с бинарной совместимостью. Эту задачу можно запустить в IntelliJ IDEA или из командной строки в каталоге проекта:

./gradlew checkLegacyAbi

Эта задача создает дамп двоичного интерфейса приложения (ABI) из текущего кода в виде текстового файла UTF-8. Затем задача сравнивает новый дамп с дампом предыдущего выпуска. Если задача обнаруживает различия, она сообщает о них как об ошибках. Проверив ошибки и решив, что изменения допустимы, можно обновить эталонный дамп ABI, запустив задачу Gradle updateLegacyAbi.

Фильтрация классов

Эта функция позволяет фильтровать классы в дампе ABI. Можно явно включать или исключать классы по полному или частичному имени, а также по аннотациям (или частям их имен), которыми они помечены.

Например, этот пример исключает все классы из пакета com.company:

// build.gradle.kts
kotlin {
    @OptIn(org.jetbrains.kotlin.gradle.dsl.abi.ExperimentalAbiValidation::class)
    abiValidation {
        filters.excluded.byNames.add("com.company.**")
    }
}

Подробнее о настройке средства проверки бинарной совместимости см. в справочнике API KGP.

Ограничения мультиплатформенности

В мультиплатформенных проектах, если хостовая система не поддерживает кросс-компиляцию для всех целевых платформ, KGP пытается определить изменения ABI для неподдерживаемых платформ, проверяя дампы ABI других платформ. Такой подход позволяет избежать ложных срабатываний при проверке, если впоследствии вы переключитесь на хостовую систему, которая может компилировать все целевые платформы.

Можно изменить это поведение по умолчанию, чтобы KGP не определял изменения ABI для неподдерживаемых платформ. Для этого добавьте следующий код в файл build.gradle.kts:

// build.gradle.kts
kotlin {
    @OptIn(org.jetbrains.kotlin.gradle.dsl.abi.ExperimentalAbiValidation::class)
    abiValidation {
        klib {
            keepUnsupportedTargets = false
        }
    }
}

Однако, если в проекте есть неподдерживаемая целевая платформа, запуск задачи checkLegacyAbi завершится с ошибкой, поскольку задача не может создать дамп ABI. Такое поведение может быть предпочтительным, если важнее, чтобы проверка завершилась с ошибкой, чем чтобы несовместимое изменение осталось незамеченным из-за выводов об изменениях ABI на основе других целевых платформ.

Поддержка расширенного вывода в консоли плагина Kotlin Gradle

В Kotlin 2.2.0 добавлена поддержка цветного и другого расширенного вывода в консоли во время сборки Gradle, что упрощает чтение и понимание диагностических сообщений.

Расширенный вывод доступен в поддерживаемых эмуляторах терминала для Linux и macOS; мы работаем над добавлением поддержки Windows.

Gradle console

Эта функция включена по умолчанию. Чтобы переопределить это поведение, добавьте следующее свойство Gradle в файл gradle.properties:

org.gradle.console=plain

Подробнее об этом свойстве и его параметрах см. в документации Gradle, в разделе Настройка формата журнала.

Интеграция Problems API в диагностику KGP

Ранее плагин Kotlin Gradle (KGP) мог сообщать о диагностических событиях, таких как предупреждения и ошибки, только в виде обычного текста в консоли или журналах.

Начиная с версии 2.2.0, в KGP появился дополнительный механизм формирования отчетов: теперь он использует Problems API Gradle — стандартизированный способ предоставления подробной структурированной информации о проблемах во время сборки.

Теперь диагностику KGP проще читать, и она более единообразно отображается в различных интерфейсах, таких как CLI Gradle и IntelliJ IDEA.

Эта интеграция включена по умолчанию начиная с Gradle 8.6. Поскольку API продолжает развиваться, используйте последнюю версию Gradle, чтобы получать самые свежие улучшения.

Совместимость KGP с --warning-mode

Диагностика плагина Kotlin Gradle (KGP) сообщала о проблемах с фиксированными уровнями серьезности, поэтому параметр командной строки Gradle --warning-mode не влиял на отображение ошибок KGP.

Теперь диагностика KGP совместима с параметром --warning-mode, что обеспечивает большую гибкость. Например, можно преобразовать все предупреждения в ошибки или полностью отключить предупреждения.

После этого изменения диагностика KGP корректирует вывод в соответствии с выбранным режимом предупреждений:

  • При установке --warning-mode=fail диагностика с уровнем Severity.Warning теперь повышается до уровня Severity.Error.

  • При установке --warning-mode=none диагностика с уровнем Severity.Warning не записывается в журнал.

Это поведение включено по умолчанию начиная с версии 2.2.0.

Чтобы игнорировать параметр --warning-mode, задайте следующее свойство Gradle в файле gradle.properties:

kotlin.internal.diagnostics.ignoreWarningMode=true

Новый экспериментальный API инструментов сборки

Kotlin можно использовать с различными системами сборки, такими как Gradle, Maven, Amper и другие. Однако интеграция Kotlin с каждой системой для поддержки полного набора функций, таких как инкрементальная компиляция и совместимость с плагинами компилятора Kotlin, демонами и Kotlin Multiplatform, требует значительных усилий.

Чтобы упростить этот процесс, в Kotlin 2.2.0 представлен новый экспериментальный API инструментов сборки (BTA). BTA — это универсальный API, выступающий в качестве уровня абстракции между системами сборки и экосистемой компилятора Kotlin. При таком подходе каждой системе сборки нужно поддерживать только одну точку входа BTA.

В настоящее время BTA поддерживает только Kotlin/JVM. Команда Kotlin в JetBrains уже использует его в плагине Kotlin Gradle (KGP) и kotlin-maven-plugin. Вы можете попробовать BTA с помощью этих плагинов, но сам API пока не готов к общему использованию в собственных интеграциях с инструментами сборки. Если вам интересна концепция BTA или вы хотите поделиться отзывом, ознакомьтесь с предложением KEEP.

Чтобы попробовать BTA в следующих инструментах:

  • Для KGP добавьте следующее свойство в файл gradle.properties:

kotlin.compiler.runViaBuildToolsApi=true
  • Для Maven ничего делать не нужно. Эта функция включена по умолчанию.

В настоящее время BTA не дает прямых преимуществ для плагина Maven, но закладывает прочную основу для ускоренного внедрения новых функций, таких как поддержка демона Kotlin и стабилизация инкрементальной компиляции.

Использование BTA в KGP уже дает следующие преимущества:

  • Улучшенная стратегия выполнения компилятора «в процессе»

  • Больше гибкости при настройке версий компилятора Kotlin

Улучшенная стратегия выполнения компилятора «в процессе»

KGP поддерживает три стратегии выполнения компилятора Kotlin. Стратегия «в процессе», при которой компилятор запускается внутри процесса демона Gradle, ранее не поддерживала инкрементальную компиляцию.

Теперь благодаря BTA стратегия «в процессе» поддерживает инкрементальную компиляцию. Чтобы использовать ее, добавьте следующее свойство в файл gradle.properties:

kotlin.compiler.execution.strategy=in-process

Гибкая настройка различных версий компилятора Kotlin

Иногда может потребоваться использовать в коде более новую версию компилятора Kotlin, оставив KGP на старой версии, — например, чтобы попробовать новые языковые возможности и при этом продолжить работу над устаревшими элементами скриптов сборки. Или же может понадобиться обновить версию KGP, оставив старую версию компилятора Kotlin.

BTA позволяет это сделать. Вот как настроить его в файле build.gradle.kts:

// build.gradle.kts
import org.jetbrains.kotlin.buildtools.api.ExperimentalBuildToolsApi
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi

plugins { 
    kotlin("jvm") version "2.2.0"
}

group = "org.jetbrains.example"
version = "1.0-SNAPSHOT"

repositories { 
    mavenCentral()
}

kotlin { 
    jvmToolchain(8)
    @OptIn(ExperimentalBuildToolsApi::class, ExperimentalKotlinGradlePluginApi::class) 
    compilerVersion.set("2.1.21") // Different version than 2.2.0
}

BTA поддерживает настройку версий KGP и компилятора Kotlin в пределах трех предыдущих основных версий и одной последующей основной версии. Поэтому в KGP 2.2.0 поддерживаются версии компилятора Kotlin 2.1.x, 2.0.x и 1.9.25. KGP 2.2.0 также совместим с будущими версиями компилятора Kotlin 2.2.x и 2.3.x.

Однако имейте в виду, что совместное использование разных версий компилятора и плагинов компилятора может привести к исключениям компилятора Kotlin. Команда Kotlin планирует устранить подобные проблемы в будущих выпусках.

Попробуйте BTA с этими плагинами и отправьте отзыв в соответствующие задачи YouTrack для KGP и плагина Maven.

Стандартная библиотека

В Kotlin 2.2.0 API Base64 и HexFormat получили статус стабильных.

Стабильное кодирование и декодирование Base64

В Kotlin 1.8.20 была добавлена экспериментальная поддержка кодирования и декодирования Base64. В Kotlin 2.2.0 API Base64 получил статус стабильного и включает четыре схемы кодирования. В этом выпуске добавлена новая схема Base64.Pem:

  • Base64.Default использует стандартную схему кодирования Base64.

    Base64.Default — это companion-объект класса Base64. Поэтому его функции можно вызывать с помощью Base64.encode() и Base64.decode() вместо Base64.Default.encode() и Base64.Default.decode().

  • Base64.UrlSafe использует схему кодирования «безопасную для URL и имен файлов».

  • Base64.Mime использует схему кодирования MIME: при кодировании через каждые 76 символов вставляется разделитель строк, а при декодировании пропускаются недопустимые символы.

  • Base64.Pem кодирует данные так же, как Base64.Mime, но ограничивает длину строки 64 символами.

С помощью API Base64 можно кодировать двоичные данные в строку Base64 и декодировать ее обратно в байты.

Пример:

val foBytes = "fo".map { it.code.toByte() }.toByteArray()
Base64.Default.encode(foBytes) // "Zm8="
// Alternatively:
// Base64.encode(foBytes)

val foobarBytes = "foobar".map { it.code.toByte() }.toByteArray()
Base64.UrlSafe.encode(foobarBytes) // "Zm9vYmFy"

Base64.Default.decode("Zm8=") // foBytes
// Alternatively:
// Base64.decode("Zm8=")

Base64.UrlSafe.decode("Zm9vYmFy") // foobarBytes

В JVM используйте функции-расширения .encodingWith() и .decodingWith() для кодирования и декодирования Base64 с помощью потоков ввода и вывода:

import kotlin.io.encoding.*
import java.io.ByteArrayOutputStream

fun main() {
    val output = ByteArrayOutputStream()
    val base64Output = output.encodingWith(Base64.Default)

    base64Output.use { stream ->
        stream.write("Hello World!!".encodeToByteArray()) 
    }

    println(output.toString())
    // SGVsbG8gV29ybGQhIQ==
}

Стабильный разбор и форматирование шестнадцатеричных чисел с помощью API HexFormat

API HexFormat, представленный в Kotlin 1.9.0, теперь получил статус стабильного. С его помощью можно преобразовывать числовые значения в шестнадцатеричные строки и обратно.

Например:

fun main() {
    //sampleStart
    println(93.toHexString())
    //sampleEnd
}

Подробнее см. в разделе Новый класс HexFormat для форматирования и разбора шестнадцатеричных чисел.

Компилятор Compose

В этом выпуске компилятор Compose получил поддержку ссылок на composable-функции, а значения по умолчанию для нескольких флагов функций изменились.

Поддержка ссылок на @Composable-функции

Начиная с выпуска Kotlin 2.2.0 компилятор Compose поддерживает объявление и использование ссылок на composable-функции:

val content: @Composable (String) -> Unit = ::Text

@Composable fun App() {
    content("My App")
}

Ссылки на composable-функции во время выполнения немного отличаются от объектов composable-лямбд. В частности, composable-лямбды обеспечивают более точный контроль над пропуском, наследуясь от класса ComposableLambda. От ссылок на функции ожидается реализация интерфейса KCallable, поэтому применить к ним такую же оптимизацию нельзя.

Флаг функции PausableComposition включен по умолчанию

Флаг функции PausableComposition включен по умолчанию начиная с Kotlin 2.2.0. Этот флаг изменяет вывод компилятора Compose для перезапускаемых функций, позволяя среде выполнения принудительно пропускать их и тем самым фактически приостанавливать композицию. Благодаря этому тяжелые композиции можно разделять между кадрами; эта возможность будет использоваться при предварительной загрузке в одном из будущих выпусков.

Чтобы отключить этот флаг функции, добавьте следующий код в конфигурацию Gradle:

// build.gradle.kts
composeCompiler {
    featureFlag = setOf(ComposeFeatureFlag.PausableComposition.disabled())
}

Флаг функции OptimizeNonSkippingGroups включен по умолчанию

Флаг функции OptimizeNonSkippingGroups включен по умолчанию начиная с Kotlin 2.2.0. Эта оптимизация повышает производительность во время выполнения, удаляя вызовы групп, сгенерированные для composable-функций, которые нельзя пропустить. Она не должна приводить к каким-либо наблюдаемым изменениям поведения во время выполнения.

Если вы столкнулись с проблемами, отключите этот флаг функции, чтобы проверить, вызвано ли изменение именно ими. Сообщайте о проблемах в систему отслеживания проблем Jetpack Compose.

Чтобы отключить флаг OptimizeNonSkippingGroups, добавьте следующий код в конфигурацию Gradle:

composeCompiler {
    featureFlag = setOf(ComposeFeatureFlag.OptimizeNonSkippingGroups.disabled())
}

Устаревшие флаги функций

Флаги функций StrongSkipping и IntrinsicRemember теперь считаются устаревшими и будут удалены в одном из будущих выпусков. Если вы столкнулись с проблемами, из-за которых приходится отключать эти флаги функций, сообщите о них в систему отслеживания проблем Jetpack Compose.

Несовместимые изменения и устаревшие элементы

В этом разделе описаны важные несовместимые изменения и устаревшие элементы, на которые стоит обратить внимание. Полный обзор всех несовместимых изменений и устаревших элементов этого выпуска см. в руководстве по совместимости.

  • Начиная с Kotlin 2.2.0 компилятор больше не поддерживает -language-version=1.6 или -language-version=1.7. Наборы языковых возможностей старше версии 1.8 не поддерживаются, однако сам язык остается полностью обратно совместимым с Kotlin 1.0.

  • Поддержка системы сборки Ant объявлена устаревшей. Поддержка Ant в Kotlin уже давно не развивается, и мы не планируем продолжать ее поддержку из-за относительно небольшой пользовательской базы. Мы планируем удалить поддержку Ant в версии 2.3.0.

  • В Kotlin 2.2.0 уровень устаревания блока kotlinOptions{} в Gradle повышен до уровня ошибки. Вместо него используйте блок compilerOptions{}. Инструкции по обновлению скриптов сборки см. в разделе Переход с kotlinOptions{} на compilerOptions{}.

  • Скриптинг Kotlin остается важной частью экосистемы Kotlin, однако мы сосредоточиваемся на отдельных сценариях использования, таких как пользовательские скрипты, а также скрипты gradle.kts и main.kts, чтобы обеспечить более удобную работу. Подробнее см. в обновленной публикации в блоге. В связи с этим в Kotlin 2.2.0 объявлена устаревшей поддержка следующих возможностей:

    • REPL: чтобы продолжить использовать REPL через kotlinc, включите его с помощью параметра компилятора -Xrepl.

    • JSR-223: поскольку этот JSR находится в состоянии «Отозван», реализация JSR-223 продолжает работать с языковой версией 1.9, но в будущем не будет перенесена на компилятор K2.

    • Плагин Maven KotlinScriptMojo: этот плагин не получил достаточного распространения. При дальнейшем его использовании будут появляться предупреждения компилятора.

  • В Kotlin 2.2.0 функция setSource() в KotlinCompileTool теперь заменяет настроенные исходные файлы, а не добавляет их к существующим. Если нужно добавить исходные файлы, не заменяя существующие, используйте функцию source().

  • Тип свойства annotationProcessorOptionProviders в BaseKapt изменен с MutableList<Any> на MutableList<CommandLineArgumentProvider>. Если сейчас ваш код добавляет список как один элемент, используйте функцию addAll() вместо функции add().

  • После устаревания инструмента устранения неиспользуемого кода (DCE), применявшегося в прежней серверной части Kotlin/JS, из плагина Kotlin Gradle удалены оставшиеся DSL, связанные с DCE:

    • Интерфейс org.jetbrains.kotlin.gradle.dsl.KotlinJsDce

    • Функция org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl.dceTask(body: Action<KotlinJsDce>)

    • Интерфейс org.jetbrains.kotlin.gradle.dsl.KotlinJsDceCompilerToolOptions

    • Интерфейс org.jetbrains.kotlin.gradle.dsl.KotlinJsDceOptions

    Текущий компилятор JS IR поддерживает DCE из коробки, а аннотация @JsExport позволяет указать, какие функции и классы Kotlin следует сохранить при DCE.

  • Устаревший плагин kotlin-android-extensions удален в Kotlin 2.2.0. Вместо него используйте плагин kotlin-parcelize для генератора реализаций Parcelable, а для синтетических представлений — привязки представлений Android Jetpack.

  • Экспериментальный API kotlinArtifacts объявлен устаревшим в Kotlin 2.2.0. Используйте текущий DSL плагина Kotlin Gradle, чтобы собирать готовые нативные бинарные файлы. Если этого недостаточно для перехода, оставьте комментарий в этой задаче YouTrack.

  • KotlinCompilation.source, объявленный устаревшим в Kotlin 1.9.0, теперь удален из плагина Kotlin Gradle.

  • Параметры экспериментальных режимов объединения кода объявлены устаревшими в Kotlin 2.2.0. Очистите кэш объединения кода, чтобы удалить недействительные артефакты компиляции.

  • Устаревшее свойство konanVersion теперь удалено из задачи CInteropProcess. Вместо него используйте CInteropProcess.kotlinNativeVersion.

  • Использование устаревшего свойства destinationDir теперь приведет к ошибке. Вместо него используйте CInteropProcess.destinationDirectory.set().

Обновления документации

В этом выпуске появились заметные изменения в документации, включая перенос документации по Kotlin Multiplatform на портал KMP.

Кроме того, мы создали новые страницы и руководства, а также обновили существующие.

Новые и обновлённые руководства

  • Промежуточный тур по Kotlin – Углубите свои знания Kotlin. Узнайте, когда использовать функции-расширения, интерфейсы, классы и многое другое.

  • Создание приложения на Kotlin с использованием Spring AI – Узнайте, как создать приложение на Kotlin, которое отвечает на вопросы с помощью OpenAI и векторной базы данных.

  • Создание проекта Spring Boot на Kotlin – Узнайте, как создать проект Spring Boot с помощью Gradle и мастера Новый проект в IntelliJ IDEA.

  • Серия руководств по сопоставлению Kotlin и C – Узнайте, как сопоставляются различные типы и конструкции в Kotlin и C.

  • Создание приложения с помощью взаимодействия с C и libcurl – Создайте простой HTTP-клиент, который может работать в нативной среде с использованием библиотеки C libcurl.

  • Создание библиотеки Kotlin Multiplatform – Узнайте, как создать и опубликовать мультиплатформенную библиотеку с помощью IntelliJ IDEA.

  • Создание полнофункционального приложения с помощью Ktor и Kotlin Multiplatform – В этом руководстве вместо Fleet теперь используется IntelliJ IDEA, а также Material 3 и последние версии Ktor и Kotlin.

  • Управление локальной средой ресурсов в приложении Compose Multiplatform – Узнайте, как управлять средой ресурсов приложения, например темой и языком внутри приложения.

Новые и обновлённые страницы

  • Обзор Kotlin для ИИ – Узнайте о возможностях Kotlin для создания приложений на основе ИИ.

  • Руководство по миграции Dokka – Узнайте, как перейти на версию 2 плагина Dokka Gradle.

  • Библиотека Kotlin Metadata JVM – Изучите рекомендации по чтению, изменению и созданию метаданных классов Kotlin, скомпилированных для JVM.

  • Интеграция с CocoaPods – Узнайте, как настроить среду, добавить зависимости Pod или использовать проект Kotlin в качестве зависимости CocoaPod, следуя руководствам и примерам проектов.

  • Новые страницы Compose Multiplatform, посвящённые стабильному выпуску для iOS:

    • Навигация и, в частности, глубокие ссылки.

    • Реализация макетов в Compose.

    • Локализация строк и другие страницы по интернационализации, например о поддержке языков с письмом справа налево.

  • Compose Hot Reload – Узнайте, как использовать Compose Hot Reload для настольных целевых платформ и добавлять его в существующий проект.

  • Миграции Exposed – Узнайте об инструментах Exposed для управления изменениями схемы базы данных.

Как обновиться до Kotlin 2.2.0

Плагин Kotlin распространяется как встроенный плагин в IntelliJ IDEA и Android Studio.

Чтобы обновиться до новой версии Kotlin, измените версию Kotlin на 2.2.0 в сценариях сборки.

27 марта 2026 г.
Что нового в Kotlin 2.2.20Руководство по совместимости для Kotlin 2.2.x

© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/whatsnew22.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API