新しいメモリマネージャーへの移行
レガシーメモリマネージャーのサポートは、Kotlin 1.9.20 で完全に削除されました。Kotlin 1.7.20 以降でデフォルトで有効になっている現在のメモリモデルにプロジェクトを移行してください。
このガイドでは、新しい Kotlin/Native メモリマネージャーをレガシーなものと比較し、プロジェクトの移行方法について説明します。
新しいメモリマネージャーにおける最も顕著な変更点は、オブジェクト共有に関する制限が解除されたことです。スレッド間でオブジェクトを共有するためにオブジェクトをフリーズ(freeze)する必要はありません。具体的には以下の通りです:
- トップレベルのプロパティは、
@SharedImmutableを使用せずに任意のスレッドからアクセスおよび変更できます。 - インターオペラビリティ(interop)を介して渡されるオブジェクトは、フリーズすることなく任意のスレッドからアクセスおよび変更できます。
Worker.executeAfterは、オペレーションをフリーズさせる必要がなくなりました。Worker.executeは、プロデューサーが分離されたオブジェクトサブグラフ(isolated object subgraph)を返す必要がなくなりました。AtomicReferenceおよびFreezableAtomicReferenceを含む循環参照は、メモリリークを引き起こしません。
オブジェクト共有が容易になったこと以外にも、新しいメモリマネージャーにはいくつかの大きな変更点があります:
- グローバルプロパティは、それが定義されているファイルに最初にアクセスしたときに遅延初期化されます。以前は、グローバルプロパティはプログラムの起動時に初期化されていました。回避策として、プログラムの開始時に初期化する必要があるプロパティには
@EagerInitializationアノテーションを付けることができます。使用する前に、そのドキュメントを確認してください。 by lazy {}プロパティはスレッドセーフモードをサポートし、制限のない再帰(unbounded recursion)は処理しません。Worker.executeAfter内のoperationから発生した例外は、他のランタイム部分と同様に処理されます。具体的には、ユーザー定義の未処理例外フック(unhandled exception hook)の実行を試みるか、フックが見つからない、またはフック自体が例外で失敗した場合はプログラムを終了します。- フリーズ(Freezing)は非推奨となり、常に無効化されます。
レガシーメモリマネージャーからプロジェクトを移行するには、以下のガイドラインに従ってください:
Kotlin のアップデート
新しい Kotlin/Native メモリマネージャーは、Kotlin 1.7.20 以降、デフォルトで有効になっています。Kotlin のバージョンを確認し、必要に応じて最新バージョンにアップデートしてください。
依存関係のアップデート
バージョン 1.6.0 以降にアップデートしてください。native-mt サフィックスが付いたバージョンは使用しないでください。
新しいメモリマネージャーに関して、留意すべきいくつかの特記事項もあります:
- フリーズが不要になったため、すべての一般的なプリミティブ(チャネル、フロー、コルーチン)は Worker の境界を越えて動作します。
Dispatchers.Defaultは、Linux および Windows では Worker のプール、Apple ターゲットではグローバルキューによってバックアップされます。- Worker によってバックアップされるコルーチンディスパッチャを作成するには、
newSingleThreadContextを使用します。 N個の Worker のプールによってバックアップされるコルーチンディスパッチャを作成するには、newFixedThreadPoolContextを使用します。Dispatchers.Mainは、Darwin ではメインキュー、その他のプラットフォームではスタンドアロンの Worker によってバックアップされます。
大部分のライブラリは変更なしで動作するはずですが、例外がある場合があります。
依存関係を最新バージョンに更新し、レガシーメモリマネージャー用と新しいメモリマネージャー用のライブラリバージョンに違いがないことを確認してください。
コードのアップデート
新しいメモリマネージャーをサポートするために、影響を受ける API の使用箇所を削除してください:
| 旧 API | 対応方法 |
|---|---|
@SharedImmutable | すべての使用箇所を削除できます。ただし、新しいメモリマネージャーでこの API を使用しても警告は出ません。 |
FreezableAtomicReference クラス | 代わりに AtomicReference を使用してください。 |
FreezingException クラス | すべての使用箇所を削除してください。 |
InvalidMutabilityException クラス | すべての使用箇所を削除してください。 |
IncorrectDereferenceException クラス | すべての使用箇所を削除してください。 |
freeze() 関数 | すべての使用箇所を削除してください。 |
isFrozen プロパティ | すべての使用箇所を削除できます。フリーズは非推奨であるため、このプロパティは常に false を返します。 |
ensureNeverFrozen() 関数 | すべての使用箇所を削除してください。 |
atomicLazy() 関数 | 代わりに lazy() を使用してください。 |
MutableData クラス | 代わりに任意の通常のコレクションを使用してください。 |
WorkerBoundReference<out T : Any> クラス | T を直接使用してください。 |
DetachedObjectGraph<T> クラス | T を直接使用してください。C インターオペラビリティを介して値を渡すには、StableRef クラスを使用してください。 |
