Skip to content

Kotlin 2.2.0の新機能

リリース日: 2025年6月23日

Kotlin 2.2.0がリリースされました!主なハイライトは以下の通りです。

Kotlin Language Evolutionチームが新機能について議論し、質問に答えるこのビデオもご覧ください。

IDEサポート

2.2.0をサポートするKotlinプラグインは、IntelliJ IDEAおよびAndroid Studioの最新バージョンに同梱されています。 IDEのKotlinプラグインを更新する必要はありません。 必要なのは、ビルドスクリプトでKotlinのバージョンを2.2.0に変更するだけです。

詳細は新しいリリースへのアップデートを参照してください。

言語

このリリースでは、ガード条件、非ローカルなbreakcontinue、複数ドル記号による文字列補間が安定版に昇格しました。 さらに、コンテキストパラメータコンテキスト依存の解決などのいくつかの機能がプレビューとして導入されました。

Experimental

コンテキストパラメータのプレビュー

コンテキストパラメータを使用すると、関数とプロパティは、周囲のコンテキストで暗黙的に利用可能な依存関係を宣言できます。

コンテキストパラメータを使用すると、サービスや依存関係など、共有され、関数呼び出しのセット間でめったに変更されない値を手動で渡す必要がなくなります。

コンテキストパラメータは、コンテキストレシーバと呼ばれる以前の実験的な機能を置き換えます。コンテキストレシーバからコンテキストパラメータに移行するには、ブログ記事で説明されているように、IntelliJ IDEAの支援機能を使用できます。

主な違いは、コンテキストパラメータが関数の本体にレシーバとして導入されない点です。結果として、コンテキストが暗黙的に利用可能だったコンテキストレシーバとは異なり、コンテキストパラメータの名前を使用してそのメンバーにアクセスする必要があります。

Kotlinのコンテキストパラメータは、簡素化された依存性注入、改善されたDSL設計、およびスコープ付き操作を通じて、依存関係の管理において大幅な改善をもたらします。詳細については、この機能のKEEPを参照してください。

コンテキストパラメータの宣言方法

contextキーワードの後にname: Typeの形式のパラメータのリストを続けることで、プロパティや関数にコンテキストパラメータを宣言できます。以下は、UserServiceインターフェースへの依存関係を持つ例です。

kotlin
// UserServiceはコンテキストで必要な依存関係を定義します 
interface UserService {
    fun log(message: String)
    fun findUserById(id: Int): String
}

// コンテキストパラメータを持つ関数を宣言します
context(users: UserService)
fun outputMessage(message: String) {
    // コンテキストからlogを使用します
    users.log("Log: $message")
}

// コンテキストパラメータを持つプロパティを宣言します
context(users: UserService)
val firstUser: String
    // コンテキストからfindUserByIdを使用します    
    get() = users.findUserById(1)

コンテキストパラメータ名として_を使用できます。この場合、パラメータの値は解決に利用できますが、ブロック内で名前によってアクセスすることはできません。

kotlin
// コンテキストパラメータ名として"_"を使用
context(_: UserService)
fun logWelcome() {
    // UserServiceから適切なlog関数を見つけます
    outputMessage("Welcome!")
}

コンテキストパラメータを有効にする方法

プロジェクトでコンテキストパラメータを有効にするには、コマンドラインで以下のコンパイラオプションを使用します。

Bash
-Xcontext-parameters

または、GradleビルドファイルのcompilerOptions {}ブロックに追加します。

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

-Xcontext-receivers-Xcontext-parametersの両方のコンパイラオプションを同時に指定するとエラーになります。

フィードバックにご協力ください

この機能は、今後のKotlinリリースで安定化され、改善される予定です。 課題トラッカーYouTrackへのフィードバックをお待ちしております。

Experimental

コンテキスト依存の解決のプレビュー

Kotlin 2.2.0は、コンテキスト依存の解決のプレビュー版実装を導入します。

以前は、型がコンテキストから推論できる場合でも、enumエントリまたはsealedクラスのメンバーの完全な名前を記述する必要がありました。 例:

kotlin
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"
}

現在、コンテキスト依存の解決により、期待される型が既知であるコンテキストでは、型名を省略できます。

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

// 問題の既知の型に基づいてenumエントリを解決します
fun message(problem: Problem): String = when (problem) {
    CONNECTION -> "connection"
    AUTHENTICATION -> "authentication"
    DATABASE -> "database"
    UNKNOWN -> "unknown"
}

コンパイラは、このコンテキストの型情報を使用して、正しいメンバーを解決します。この情報には、とりわけ以下が含まれます。

  • when式の対象
  • 明示的な戻り値の型
  • 宣言された変数型
  • 型チェック (is) およびキャスト (as)
  • sealedクラス階層の既知の型
  • パラメータの宣言された型

コンテキスト依存の解決は、関数、パラメータを持つプロパティ、またはレシーバを持つ拡張プロパティには適用されません。

プロジェクトでコンテキスト依存の解決を試すには、コマンドラインで以下のコンパイラオプションを使用します。

bash
-Xcontext-sensitive-resolution

または、GradleビルドファイルのcompilerOptions {}ブロックに追加します。

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

私たちは、今後のKotlinリリースでこの機能を安定化させ、改善していく予定です。課題トラッカーYouTrackへのフィードバックをお待ちしております。

Experimental

アノテーション使用サイトターゲット機能のプレビュー

Kotlin 2.2.0は、アノテーションの使用サイトターゲットとの連携をより便利にするいくつかの機能を導入します。

Experimental

プロパティの`@all`メタターゲット

Kotlinでは、使用サイトターゲットとして知られる、宣言の特定の箇所にアノテーションを付加できます。 しかし、各ターゲットに個別にアノテーションを付けるのは複雑でエラーが発生しやすいものでした。

kotlin
data class User(
    val username: String,

    @param:Email      // コンストラクタパラメータ
    @field:Email      // バッキングフィールド
    @get:Email        // ゲッターメソッド
    @property:Email   // Kotlinプロパティ参照
    val email: String,
) {
    @field:Email
    @get:Email
    @property:Email
    val secondaryEmail: String? = null
}

これを簡素化するために、Kotlinはプロパティ用の新しい@allメタターゲットを導入します。 この機能は、コンパイラに、プロパティの関連するすべての箇所にアノテーションを適用するように指示します。@allを使用すると、アノテーションは以下に適用しようとします。

  • param: プライマリコンストラクタで宣言されている場合、コンストラクタパラメータ。

  • property: Kotlinプロパティ自体。

  • field: 存在する場合、バッキングフィールド。

  • get: ゲッターメソッド。

  • set_param: プロパティがvarとして定義されている場合、セッターメソッドのパラメータ。

  • RECORD_COMPONENT: クラスが@JvmRecordである場合、アノテーションはJavaレコードコンポーネントに適用されます。この動作は、Javaがレコードコンポーネントのアノテーションを処理する方法を模倣しています。

コンパイラは、指定されたプロパティのターゲットにのみアノテーションを適用します。

以下の例では、@Emailアノテーションは各プロパティの関連するすべてのターゲットに適用されます。

kotlin
data class User(
    val username: String,

    // @Emailをparam、property、field、
    // get、set_param(varの場合)に適用します
    @all:Email val email: String,
) {
    // @Emailをproperty、field、およびgetterに適用します 
    // (コンストラクタにはないためparamなし)
    @all:Email val secondaryEmail: String? = null
}

プライマリコンストラクタの内外を問わず、任意のプロパティで@allメタターゲットを使用できます。ただし、複数のアノテーション@allメタターゲットを使用することはできません。

この新機能は、構文を簡素化し、一貫性を確保し、Javaレコードとの相互運用性を向上させます。

プロジェクトで@allメタターゲットを有効にするには、コマンドラインで以下のコンパイラオプションを使用します。

Bash
-Xannotation-target-all

または、GradleビルドファイルのcompilerOptions {}ブロックに追加します。

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

この機能はプレビュー段階です。問題が発生した場合は、課題トラッカーYouTrackまでご報告ください。 @allメタターゲットの詳細については、このKEEP提案を参照してください。

Experimental

使用サイトアノテーションターゲットの新しいデフォルトルール

Kotlin 2.2.0は、パラメータ、フィールド、プロパティにアノテーションを伝播するための新しいデフォルトルールを導入します。 以前はアノテーションがデフォルトでparampropertyfieldのいずれか1つにのみ適用されていましたが、現在はアノテーションに期待されるものとより一致するようになりました。

複数の適用可能なターゲットがある場合、以下のように1つ以上が選択されます。

  • コンストラクタパラメータターゲット (param) が適用可能な場合、それが使用されます。
  • プロパティターゲット (property) が適用可能な場合、それが使用されます。
  • フィールドターゲット (field) が適用可能でpropertyが適用可能でない場合、fieldが使用されます。

複数のターゲットがあり、parampropertyfieldのいずれも適用できない場合、アノテーションはエラーになります。

この機能を有効にするには、GradleビルドファイルのcompilerOptions {}ブロックに追加します。

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

または、コンパイラのコマンドライン引数を使用します。

Bash
-Xannotation-default-target=param-property

古い動作を使用したい場合は、次のことができます。

  • 特定のケースでは、例えば@Annotationの代わりに@param:Annotationを使用するなど、必要なターゲットを明示的に定義します。

  • プロジェクト全体では、Gradleビルドファイルでこのフラグを使用します。

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

この機能はプレビュー段階です。問題が発生した場合は、課題トラッカーYouTrackまでご報告ください。 アノテーション使用サイトターゲットの新しいデフォルトルールの詳細については、このKEEP提案を参照してください。

Beta

ネストされた型エイリアスのサポート

以前は、型エイリアスはKotlinファイルのトップレベルでのみ宣言できました。これは、内部またはドメイン固有の型エイリアスでさえ、使用されるクラスの外に存在する必要があることを意味していました。

2.2.0以降、外側のクラスから型パラメータをキャプチャしない限り、他の宣言内で型エイリアスを定義できます。

kotlin
class Dijkstra {
    typealias VisitedNodes = Set<Node>

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

ネストされた型エイリアスには、型パラメータを参照できないなど、いくつかの追加の制約があります。全ルールセットについてはドキュメントを参照してください。

ネストされた型エイリアスは、カプセル化の向上、パッケージレベルの煩雑さの軽減、内部実装の簡素化により、よりクリーンで保守しやすいコードを可能にします。

ネストされた型エイリアスを有効にする方法

プロジェクトでネストされた型エイリアスを有効にするには、コマンドラインで以下のコンパイラオプションを使用します。

bash
-Xnested-type-aliases

または、GradleビルドファイルのcompilerOptions {}ブロックに追加します。

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

フィードバックを共有する

ネストされた型エイリアスは現在ベータ版です。問題が発生した場合は、課題トラッカーYouTrackまでご報告ください。この機能の詳細については、このKEEP提案を参照してください。

安定版機能: ガード条件、非ローカルなbreakcontinue、および複数ドル記号による文字列補間

Kotlin 2.1.0では、いくつかの新言語機能がプレビュー段階で導入されました。 このリリースで以下の言語機能が安定版になったことをお知らせします。

Kotlinの言語設計機能と提案の全リストを参照してください

Experimental

Kotlinコンパイラ: コンパイラの警告の一元管理

Kotlin 2.2.0は、新しいコンパイラオプション-Xwarning-levelを導入します。これは、Kotlinプロジェクトでコンパイラの警告を一元的に管理するための統一された方法を提供することを目的としています。

以前は、-nowarnですべての警告を無効にする、-Werrorですべての警告をコンパイルエラーにする、または-Wextraで追加のコンパイラチェックを有効にするなど、一般的なモジュール全体にわたるルールのみを適用できました。特定の警告に対して調整する唯一のオプションは-Xsuppress-warningオプションでした。

この新しいソリューションにより、一般的なルールを上書きし、特定の診断を一貫した方法で除外できます。

適用方法

新しいコンパイラオプションは以下の構文を持ちます。

bash
-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指定された警告を除き、すべての警告をエラーに昇格させます。

追加のコンパイラ警告を有効にする

コマンド説明
-Wextratrueの場合に警告を出力する、すべての追加の宣言、式、型コンパイラチェックを有効にします。
-Xwarning-level=DIAGNOSTIC_NAME:warning指定された追加のコンパイラチェックのみを有効にします。
-Wextra -Xwarning-level=DIAGNOSTIC_NAME:disabled指定されたものを除き、すべての追加チェックを有効にします。

警告リスト

一般的なルールから除外したい警告が多数ある場合、@argfileを介して別のファイルにそれらをリストできます。

フィードバックにご協力ください

新しいコンパイラオプションはまだ実験的です。問題が発生した場合は、課題トラッカーYouTrackまでご報告ください。

Kotlin/JVM

Kotlin 2.2.0はJVMに多くのアップデートをもたらします。コンパイラはJava 24バイトコードをサポートし、インターフェース関数のデフォルトメソッド生成に変更を導入します。また、このリリースではKotlinメタデータでのアノテーションの扱いを簡素化し、インライン値クラスとのJava相互運用性を向上させ、JVMレコードへのアノテーション付けのサポートを改善します。

インターフェース関数のデフォルトメソッド生成の変更点

Kotlin 2.2.0以降、インターフェースで宣言された関数は、別途設定されていない限り、JVMのデフォルトメソッドにコンパイルされます。この変更は、Kotlinの、実装を持つインターフェース関数がバイトコードにコンパイルされる方法に影響します。

この動作は、非推奨の-Xjvm-defaultオプションを置き換える、新しい安定版コンパイラオプション-jvm-defaultによって制御されます。

以下の値を使用して-jvm-defaultオプションの動作を制御できます。

  • enable (デフォルト): インターフェースにデフォルト実装を生成し、サブクラスとDefaultImplsクラスにブリッジ関数を含めます。このモードは、古いKotlinバージョンとのバイナリ互換性を維持するために使用します。
  • no-compatibility: インターフェースにデフォルト実装のみを生成します。このモードでは、互換性ブリッジとDefaultImplsクラスがスキップされるため、新しいコードに適しています。
  • disable: インターフェースのデフォルト実装を無効にします。ブリッジ関数とDefaultImplsクラスのみが生成され、Kotlin 2.2.0より前の動作と一致します。

-jvm-defaultコンパイラオプションを設定するには、Gradle Kotlin DSLでjvmDefaultプロパティを設定します。

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

Kotlinメタデータにおけるアノテーションの読み書きのサポート

以前は、コンパイルされたJVMクラスファイルからリフレクションまたはバイトコード分析を使用してアノテーションを読み取り、シグネチャに基づいてメタデータエントリに手動で一致させる必要がありました。 このプロセスは、特にオーバーロードされた関数では、エラーが発生しやすかったものでした。

現在、Kotlin 2.2.0では、Kotlinメタデータに格納されたアノテーションの読み取りのサポートが導入されます。

コンパイルされたファイルのメタデータでアノテーションを利用可能にするには、以下のコンパイラオプションを追加します。

kotlin
-Xannotations-in-metadata

または、GradleビルドファイルのcompilerOptions {}ブロックに追加します。

kotlin
// 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メタデータからアノテーションを読み取る例を以下に示します。

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バージョンでメタデータ内のアノテーションがデフォルトで有効になったときに、プロジェクトが無効または不完全なメタデータを生成する可能性があります。

問題が発生した場合は、課題トラッカーまでご報告ください。

Experimental

インライン値クラスとのJava相互運用性の改善

Kotlin 2.2.0は、新しい実験的なアノテーション@JvmExposeBoxedを導入します。このアノテーションは、Javaからインライン値クラスを使用しやすくします。

デフォルトでは、Kotlinはインライン値クラスをアンボックス化された表現を使用するようにコンパイルします。これはパフォーマンスが向上しますが、Javaから使用するのが困難または不可能な場合が多いです。例:

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

この場合、クラスがアンボックス化されているため、Javaが呼び出せるコンストラクタがありません。また、Javaがinitブロックをトリガーしてnumberが正であることを保証する方法もありません。

クラスに@JvmExposeBoxedアノテーションを付けると、KotlinはJavaが直接呼び出せるパブリックコンストラクタを生成し、initブロックも実行されることを保証します。

@JvmExposeBoxedアノテーションは、クラス、コンストラクタ、または関数レベルで適用でき、Javaに公開されるものを細かく制御できます。

例えば、以下のコードでは、拡張関数.timesTwoBoxed()はJavaからアクセスできません

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

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

MyIntクラスのインスタンスを作成し、Javaコードから.timesTwoBoxed()関数を呼び出すことを可能にするには、クラスと関数の両方に@JvmExposeBoxedアノテーションを追加します。

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

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

これらのアノテーションを使用すると、KotlinコンパイラはMyIntクラス用のJavaからアクセス可能なコンストラクタを生成します。また、値クラスのボックス化された形式を使用する拡張関数のオーバーロードも生成します。結果として、以下のJavaコードが正常に実行されます。

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

公開したいインライン値クラスのすべての部分にアノテーションを付けたくない場合、アノテーションをモジュール全体に効果的に適用できます。この動作をモジュールに適用するには、-Xjvm-expose-boxedオプションでコンパイルします。このオプションでコンパイルすると、モジュール内のすべての宣言に@JvmExposeBoxedアノテーションが付いているのと同じ効果があります。

この新しいアノテーションは、Kotlinが値クラスを内部でコンパイルまたは使用する方法を変更せず、既存のコンパイル済みコードはすべて有効なままです。Java相互運用性を向上させる新しい機能を追加するだけです。値クラスを使用するKotlinコードのパフォーマンスには影響しません。

@JvmExposeBoxedアノテーションは、メンバー関数のボックス化されたバリアントを公開し、ボックス化された戻り値の型を受け取りたいライブラリ作者にとって有用です。これにより、インライン値クラス(効率的だがKotlin専用)とデータクラス(Java互換だが常にボックス化される)のどちらかを選択する必要がなくなります。

@JvmExposedBoxedアノテーションの動作とそれが解決する問題に関するより詳細な説明については、このKEEP提案を参照してください。

JVMレコードへのアノテーション付けのサポートの改善

KotlinはKotlin 1.5.0以降、JVMレコードをサポートしています。現在、Kotlin 2.2.0は、レコードコンポーネントに対するKotlinのアノテーションの扱いを改善します。特に、JavaのRECORD_COMPONENTターゲットとの関連において、改善が見られます。

まず、RECORD_COMPONENTをアノテーションターゲットとして使用したい場合、Kotlin (@Target) とJavaのアノテーションを手動で追加する必要があります。これは、Kotlinの@TargetアノテーションがRECORD_COMPONENTをサポートしていないためです。例:

kotlin
@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:使用サイトターゲットを使用してその動作を再現できるようになりました。

例:

kotlin
@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を使用します。このリリースでは、メモリ消費量を追跡および調整するために設計されたいくつかの実験的機能も導入します。

Experimental

オブジェクトごとのメモリ割り当て

Kotlin/Nativeのメモリ割り当てツールは、オブジェクトごとにメモリを予約できるようになりました。場合によっては、これにより厳密なメモリ制限を満たしたり、アプリケーションの起動時のメモリ消費量を削減したりするのに役立つ場合があります。

この新機能は、デフォルトのメモリ割り当てツールの代わりにシステムメモリ割り当てツールを有効にする-Xallocator=stdコンパイラオプションを置き換えるように設計されています。現在、メモリ割り当てを切り替えることなく、バッファリング(割り当てのページング)を無効にできます。

この機能は現在実験的です。 有効にするには、gradle.propertiesファイルで以下のオプションを設定します。

none
kotlin.native.binary.pagedAllocator=false

問題が発生した場合は、課題トラッカーYouTrackまでご報告ください。

Experimental

実行時におけるLatin-1エンコード文字列のサポート

Kotlinは現在、JVMと同様に、Latin-1エンコードされた文字列をサポートするようになりました。これは、アプリケーションのバイナリサイズを削減し、メモリ消費量を調整するのに役立つはずです。

デフォルトでは、Kotlinの文字列はUTF-16エンコーディングを使用して格納され、各文字は2バイトで表現されます。場合によっては、これによりソースコードと比較して、バイナリで文字列が2倍のスペースを占めることになり、単純なASCIIファイルからデータを読み取ると、ディスクにファイルを保存するよりも2倍のメモリを消費する可能性があります。

一方、Latin-1 (ISO 8859-1)エンコーディングは、最初の256個のUnicode文字をそれぞれ1バイトで表現します。Latin-1サポートが有効になっている場合、すべての文字がその範囲内にある限り、文字列はLatin-1エンコーディングで格納されます。それ以外の場合は、デフォルトのUTF-16エンコーディングが使用されます。

Latin-1サポートを有効にする方法

この機能は現在実験的です。 有効にするには、gradle.propertiesファイルで以下のオプションを設定します。

none
kotlin.native.binary.latin1Strings=true

既知の問題

この機能が実験的である限り、cinterop拡張関数String.pinString.usePinned、およびString.refToは効率が低下します。それらへの各呼び出しは、自動的な文字列のUTF-16変換をトリガーする可能性があります。

Kotlinチームは、この機能の実装にご協力いただいたGoogleの同僚、特にSonya Valchukに深く感謝いたします。

Kotlinでのメモリ消費量の詳細については、ドキュメントを参照してください。

Appleプラットフォームにおけるメモリ消費量追跡の改善

Kotlin 2.2.0以降、Kotlinコードによって割り当てられたメモリにタグが付けられるようになりました。これは、Appleプラットフォームでのメモリ問題のデバッグに役立ちます。

アプリケーションの高いメモリ使用量を調査する際、Kotlinコードによってどれくらいのメモリが予約されているかを識別できるようになりました。Kotlinの共有メモリは識別子でタグ付けされ、Xcode InstrumentsのVM Trackerなどのツールを通じて追跡できます。

この機能はデフォルトで有効ですが、以下の_すべての_条件が満たされている場合にのみ、Kotlin/Nativeのデフォルトメモリ割り当てツールで利用可能です。

  • タグ付けが有効であること。メモリには有効な識別子でタグが付けられている必要があります。Appleは240から255の範囲の数値を推奨しており、デフォルト値は246です。

    kotlin.native.binary.mmapTag=0Gradleプロパティを設定すると、タグ付けは無効になります。

  • mmapによる割り当て。アロケータはmmapシステムコールを使用してファイルをメモリにマップする必要があります。

    kotlin.native.binary.disableMmap=trueGradleプロパティを設定すると、デフォルトのアロケータはmmapの代わりにmallocを使用します。

  • ページングが有効であること。割り当てのページング(バッファリング)が有効になっている必要があります。

    kotlin.native.binary.pagedAllocator=falseGradleプロパティを設定すると、代わりにメモリはオブジェクトごとに予約されます。

Kotlinでのメモリ消費量の詳細については、ドキュメントを参照してください。

LLVM 16から19へのアップデート

Kotlin 2.2.0では、LLVMをバージョン16から19にアップデートしました。 新しいバージョンには、パフォーマンスの改善、バグ修正、セキュリティアップデートが含まれています。

このアップデートがコードに影響を与えることはないはずですが、何か問題が発生した場合は、課題トラッカーまでご報告ください。

Windows 7ターゲットの非推奨化

Kotlin 2.2.0以降、最小サポートWindowsバージョンがWindows 7からWindows 10に引き上げられました。Microsoftが2025年1月にWindows 7のサポートを終了したため、私たちはこのレガシーターゲットを非推奨とすることを決定しました。

詳細については、ネイティブターゲットのサポートを参照してください。

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タスク
kotlinWasmNpmInstallkotlinNpmInstall
wasmRootPackageJsonrootPackageJson

同様に、新しいWasm固有の宣言が追加されました。

Wasm宣言JavaScript宣言
WasmNodeJsRootPluginNodeJsRootPlugin
WasmNodeJsPluginNodeJsPlugin
WasmYarnPluginYarnPlugin
WasmNodeJsRootExtensionNodeJsRootExtension
WasmNodeJsEnvSpecNodeJsEnvSpec
WasmYarnRootEnvSpecYarnRootEnvSpec

これにより、JavaScriptターゲットから独立してWasmターゲットを操作できるようになり、設定プロセスが簡素化されます。

この変更はデフォルトで有効になっており、追加の設定は不要です。

プロジェクトごとのBinaryen設定

Kotlin/Wasmでプロダクションビルドを最適化するために使用されるBinaryenツールは、以前はルートプロジェクトで一度だけ設定されていました。

現在、プロジェクトまたはモジュールごとにBinaryenツールを設定できるようになりました。この変更はGradleのベストプラクティスと整合し、プロジェクト分離のような機能のサポートを強化し、複雑なビルドでのビルドパフォーマンスと信頼性を向上させます。

さらに、必要に応じて、異なるモジュールに対して異なるバージョンのBinaryenを設定することもできます。

この機能はデフォルトで有効です。ただし、カスタムのBinaryen設定がある場合、ルートプロジェクトのみではなく、プロジェクトごとに適用する必要があります。

Kotlin/JS

このリリースでは、@JsPlainObjectインターフェースにおけるcopy()関数の修正@JsModuleアノテーションを持つファイルでの型エイリアス、およびその他のKotlin/JS機能が改善されています。

@JsPlainObjectインターフェースにおけるcopy()の修正

Kotlin/JSにはjs-plain-objectsという実験的なプラグインがあり、@JsPlainObjectでアノテーションされたインターフェースにcopy()関数を導入しました。copy()関数を使用してオブジェクトを操作できます。

しかし、copy()の初期実装は継承と互換性がなく、これにより@JsPlainObjectインターフェースが他のインターフェースを拡張する際に問題を引き起こしました。

プレーンオブジェクトに関する制限を回避するため、copy()関数はオブジェクト自体からそのコンパニオンオブジェクトに移動されました。

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

fun main() {
    val user = User(name = "SomeUser", age = 21)
    // この構文はもう有効ではありません
    val copy = user.copy(age = 35)      
    // こちらが正しい構文です
    val copy = User.copy(user, age = 35)
}

この変更は、継承階層の競合を解決し、曖昧さを解消します。 Kotlin 2.2.0からデフォルトで有効になります。

@JsModuleアノテーションを持つファイルにおける型エイリアスのサポート

以前は、JavaScriptモジュールから宣言をインポートするために@JsModuleでアノテーションされたファイルは、外部宣言にのみ制限されていました。これは、そのようなファイルでtypealiasを宣言できなかったことを意味します。

Kotlin 2.2.0以降、@JsModuleでマークされたファイル内で型エイリアスを宣言できます。

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

この変更はKotlin/JSの相互運用性における制限の一側面を軽減します。今後のリリースでさらなる改善が計画されています。

@JsModuleを持つファイルでの型エイリアスのサポートはデフォルトで有効になっています。

マルチプラットフォームのexpect宣言における@JsExportのサポート

Kotlinマルチプラットフォームプロジェクトでexpect/actualメカニズムを使用する場合、共通コードのexpect宣言に@JsExportアノテーションを使用することはできませんでした。

このリリースから、expect宣言に直接@JsExportを適用できます。

kotlin
// commonMain

// 以前はエラーになりましたが、現在は正しく動作します 
@JsExport
expect class WindowManager {
    fun close()
}

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

// jsMain

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

JavaScriptソースセット内の対応するactual実装にも@JsExportでアノテーションを付ける必要があり、エクスポート可能な型のみを使用する必要があります。

この修正により、commonMainで定義された共有コードをJavaScriptに正しくエクスポートできます。これにより、手動の回避策を使用することなく、マルチプラットフォームコードをJavaScriptのコンシューマに公開できるようになりました。

この変更はデフォルトで有効になっています。

Promise<Unit>型での@JsExportの使用

以前は、@JsExportアノテーションを付けてPromise<Unit>型を返す関数をエクスポートしようとすると、Kotlinコンパイラがエラーを生成しました。

Promise<Int>のような戻り値の型は正しく動作しましたが、Promise<Unit>を使用すると、「エクスポート不可能な型」の警告がトリガーされました。TypeScriptではPromise<void>に正しくマッピングされていたにもかかわらず、です。

この制限は解除されました。現在、以下のコードはエラーなしでコンパイルされます。

kotlin
// 以前は正しく動作しました
@JsExport
fun fooInt(): Promise<Int> = GlobalScope.promise {
    delay(100)
    return@promise 42
}

// 以前はエラーになりましたが、現在は正しく動作します
@JsExport
fun fooUnit(): Promise<Unit> = GlobalScope.promise {
    delay(100)
}

この変更はKotlin/JS相互運用モデルにおける不要な制限を削除します。この修正はデフォルトで有効になっています。

Gradle

Kotlin 2.2.0はGradle 7.6.3から8.14まで完全に互換性があります。最新のGradleリリースまでのGradleバージョンも使用できます。ただし、そうすると非推奨の警告が発生したり、一部の新しいGradle機能が動作しない可能性があることに注意してください。

このリリースでは、Kotlin Gradleプラグインの診断機能にいくつかの改善が加えられています。また、バイナリ互換性検証の実験的な統合が導入され、ライブラリでの作業が容易になります。

Experimental

Kotlin Gradleプラグインにバイナリ互換性検証が含まれるようになりました

ライブラリバージョン間のバイナリ互換性をチェックしやすくするために、バイナリ互換性バリデータの機能をKotlin Gradleプラグイン(KGP)に移行する実験を行っています。おもちゃのプロジェクトで試すことはできますが、まだ本番環境での使用は推奨しません。

元のバイナリ互換性バリデータは、この実験段階中も引き続きメンテナンスされます。

Kotlinライブラリは2つのバイナリフォーマットのいずれかを使用できます: JVMクラスファイルまたはklib。これらのフォーマットは互換性がないため、KGPはそれぞれを個別に処理します。

バイナリ互換性検証機能を有効にするには、build.gradle.ktsファイルのkotlin{}ブロックに以下を追加します。

kotlin
// build.gradle.kts
kotlin {
    @OptIn(org.jetbrains.kotlin.gradle.dsl.abi.ExperimentalAbiValidation::class)
    abiValidation {
        // 古いGradleバージョンとの互換性を確保するためにset()関数を使用します
        enabled.set(true)
    }
}

プロジェクトにバイナリ互換性をチェックしたい複数のモジュールがある場合、各モジュールで個別に機能を設定します。各モジュールは独自のカスタム設定を持つことができます。

有効にしたら、checkLegacyAbiGradleタスクを実行して、バイナリ互換性の問題をチェックします。タスクはIntelliJ IDEAまたはプロジェクトディレクトリのコマンドラインから実行できます。

kotlin
./gradlew checkLegacyAbi

このタスクは、現在のコードからアプリケーションバイナリインターフェース(ABI)ダンプをUTF-8テキストファイルとして生成します。タスクは、新しいダンプを以前のリリースからのものと比較します。違いが見つかった場合、それらをエラーとして報告します。エラーを確認し、変更が許容できると判断した場合は、updateLegacyAbiGradleタスクを実行して参照ABIダンプを更新できます。

クラスのフィルタリング

この機能により、ABIダンプ内のクラスをフィルタリングできます。名前または部分名で明示的にクラスを含めたり除外したり、またはそれらをマークするアノテーション(またはアノテーション名の一部)によってフィルタリングできます。

例えば、このサンプルはcom.companyパッケージ内のすべてのクラスを除外します。

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

バイナリ互換性バリデータの設定について詳しくは、KGP APIリファレンスを参照してください。

マルチプラットフォームの制限

マルチプラットフォームプロジェクトで、ホストがすべてのターゲットのクロスコンパイルをサポートしていない場合、KGPは、他のターゲットからのABIダンプをチェックすることで、サポートされていないターゲットのABI変更を推論しようとします。このアプローチは、後ですべてのターゲットをコンパイルできるホストに切り替えた場合に、誤った検証失敗を回避するのに役立ちます。

KGPがサポートされていないターゲットのABI変更を推論しないように、このデフォルトの動作を変更するには、build.gradle.ktsファイルに以下を追加します。

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

ただし、プロジェクトにサポートされていないターゲットがある場合、タスクがABIダンプを作成できないため、checkLegacyAbiタスクの実行は失敗します。この動作は、他のターゲットから推論されたABI変更による互換性のない変更を見逃すよりも、チェックが失敗する方が重要である場合に望ましいです。

Kotlin Gradleプラグインのコンソールにおけるリッチ出力のサポート

Kotlin 2.2.0では、Gradleビルドプロセス中に、コンソールでの色やその他のリッチ出力をサポートします。これにより、報告される診断情報をより読みやすく、理解しやすくします。

リッチ出力はLinuxおよびmacOSのサポートされているターミナルエミュレーターで利用可能であり、Windowsのサポート追加に取り組んでいます。

Gradle console

この機能はデフォルトで有効ですが、上書きしたい場合、gradle.propertiesファイルに以下のGradleプロパティを追加してください。

org.gradle.console=plain

このプロパティとそのオプションの詳細については、Gradleのログ形式のカスタマイズに関するドキュメントを参照してください。

KGP診断におけるProblems APIの統合

以前は、Kotlin Gradleプラグイン(KGP)は、警告やエラーなどの診断情報を、コンソールやログにプレーンテキスト出力としてしか報告できませんでした。

2.2.0以降、KGPは追加のレポートメカニズムを導入します: 現在はGradleのProblems APIを使用しています。これは、ビルドプロセス中にリッチで構造化された問題情報を報告する標準化された方法です。

KGP診断は、Gradle CLIや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.propertiesファイルに以下のGradleプロパティを設定してください。

kotlin.internal.diagnostics.ignoreWarningMode=true
Experimental

新しい実験的なビルドツールAPI

Gradle、Maven、AmperなどのさまざまなビルドシステムでKotlinを使用できます。ただし、インクリメンタルコンパイル、Kotlinコンパイラプラグイン、デーモン、Kotlin Multiplatformとの互換性など、完全な機能セットをサポートするために各システムにKotlinを統合することは、多大な労力を必要とします。

このプロセスを簡素化するために、Kotlin 2.2.0は新しい実験的なビルドツールAPI(BTA)を導入します。BTAは、ビルドシステムとKotlinコンパイラエコシステム間の抽象化レイヤーとして機能する普遍的なAPIです。このアプローチにより、各ビルドシステムは単一のBTAエントリーポイントをサポートするだけでよくなります。

現在、BTAはKotlin/JVMのみをサポートしています。JetBrainsのKotlinチームは、Kotlin Gradleプラグイン(KGP)とkotlin-maven-pluginで既にこれを使用しています。これらのプラグインを通じてBTAを試すことはできますが、API自体は、独自のビルドツール統合での一般的な使用にはまだ準備ができていません。BTAの提案に興味がある場合、またはフィードバックを共有したい場合、このKEEP提案を参照してください。

BTAを試すには:

  • KGPの場合、gradle.propertiesファイルに以下のプロパティを追加してください。
kotlin
kotlin.compiler.runViaBuildToolsApi=true
  • Mavenの場合、何もする必要はありません。デフォルトで有効になっています。

BTAは現在、Mavenプラグインに直接的なメリットはありませんが、Kotlinデーモンのサポートインクリメンタルコンパイルの安定化など、新機能のより迅速な提供のための確固たる基盤を築きます。

KGPの場合、BTAを使用することですでに以下のメリットがあります。

「インプロセス」コンパイラ実行戦略の改善

KGPは3つのKotlinコンパイラ実行戦略をサポートしています。Gradleデーモンプロセス内でコンパイラを実行する「インプロセス」戦略は、以前はインクリメンタルコンパイルをサポートしていませんでした。

現在、BTAを使用することで、「インプロセス」戦略はインクリメンタルコンパイルをサポートするようになりました。使用するには、gradle.propertiesファイルに以下のプロパティを追加してください。

kotlin
kotlin.compiler.execution.strategy=in-process

Kotlinからの異なるコンパイラバージョン設定の柔軟性

ビルドスクリプトの非推奨を処理しながら新しい言語機能を試すなど、コードで新しいKotlinコンパイラバージョンを使用しながら、KGPを古いバージョンのままにしたい場合があります。または、KGPのバージョンを更新し、古いKotlinコンパイラバージョンを保持したい場合もあります。

BTAはこれを可能にします。build.gradle.ktsファイルで次のように設定できます。

kotlin
// 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") // 2.2.0とは異なるバージョン
}

BTAは、KGPとKotlinコンパイラバージョンを、過去3つのメジャーバージョンと将来の1つのメジャーバージョンで設定することをサポートします。したがって、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を試して、KGPMavenプラグイン専用のYouTrackチケットでフィードバックをお寄せください。

Kotlin標準ライブラリ

Kotlin 2.2.0では、Base64 APIHexFormat API安定版になりました。

Base64エンコーディングとデコーディングの安定化

Kotlin 1.8.20はBase64エンコーディングとデコーディングの実験的なサポートを導入しました。 Kotlin 2.2.0では、Base64 APIは現在安定版であり、4つのエンコーディングスキームが含まれ、このリリースで新しいBase64.Pemが追加されました。

  • Base64.Defaultは、標準のBase64エンコーディングスキームを使用します。

    Base64.DefaultBase64クラスのコンパニオンオブジェクトです。 結果として、Base64.Default.encode()Base64.Default.decode()の代わりに、Base64.encode()Base64.decode()でその関数を呼び出すことができます。

  • Base64.UrlSafeは、"URLおよびファイル名セーフ"エンコーディングスキームを使用します。

  • Base64.Mimeは、MIMEエンコーディングスキームを使用し、エンコード中に76文字ごとに改行文字を挿入し、デコード中に不正な文字をスキップします。

  • Base64.PemBase64.Mimeのようにデータをエンコードしますが、行の長さを64文字に制限します。

Base64 APIを使用して、バイナリデータをBase64文字列にエンコードし、バイトにデコードするために使用できます。

以下に例を示します。

kotlin
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.Url