Kotlin

Kotlin コルーチンの例外伝搬とハンドリング完全ガイド

ⓘ本ページはプロモーションが含まれています

もっとスキルを活かしたいエンジニアへ

スポンサードリンク
働き方から選べる

無料で使えて良質な案件の情報収集ができるサービス

エンジニアの世界では、「いつでも動ける状態を作っておけ」とよく言われます。
技術やポートフォリオがあっても、自分に合う案件情報を日常的に見れていないと、いざ動こうと思った時に比較や判断が難しくなってしまいます。
普段から案件情報が集まる環境を作っておくと、良い案件が出た時にすぐ動きやすくなりますよ。
筆者自身も、メガベンチャー勤務時代に年収1,500万円を超えた経験があります。振り返ると、技術だけでなく「どんな案件や働き方があるか」を日頃から見ていたことが、キャリアの選択肢を広げるきっかけになりました。
このブログを読んでくれた方に感謝を込めて、実際に使っている情報収集サービスを紹介します。

フルリモート・週3日・高単価、どんな条件も妥協したくないなら

フリーランスボードに無料会員登録する

利用者10万人以上。業界最大規模45万件の案件。AIマッチ機能や無料の相場情報が人気。

年収800万円以上のキャリアアップ・ハイクラス正社員を視野に入れているなら

Beyond Careerに無料相談する

内定獲得率90%以上。紹介先企業とは役員クラスのコネクションがある安心と信頼できるエージェント。


スポンサードリンク

1. 例外はスコープ階層で子 → 親へ自動伝搬する

概要

Kotlin の構造化並行性では CoroutineScope がツリー構造を形成し、各 Job が親子関係を持ちます。子コルーチンが例外で失敗すると、その JobCancelled 状態になり、親の Job に通知されます(Kotlin Coroutines Guide – Structured Concurrency)。

実装例(エラーハンドリング付き)

実行結果

jobAjobB の例外が伝搬した瞬間にキャンセルされ、リソースリークを防げます。


2. launchasync の例外取得 – 安全なパターン

特性 launch async
戻り値 Job(結果なし) Deferred<T>(結果または例外を保持)
例外の流れ コルーチンコンテキストへ即時伝搬 → 未捕捉ならアプリ全体がクラッシュ await() 時に再スローされるまで保留

推奨コード

launch の内部で try / catch

async の例外は await() で取得

ポイント
async の結果を忘れると「サイレント失敗」になるので、必ず await()join() で取得しましょう。
launch 系は CoroutineExceptionHandler と併用すると未捕捉例外の一括処理が可能です(次節参照)。


3. CoroutineExceptionHandler の正しい組み合わせ

ハンドラの登録方法

SupervisorJobCoroutineExceptionHandler のベストプラクティス

  • SupervisorJob は子の失敗が他の子や親に波及しないようにする一方で、未捕捉例外はハンドラへ流れる ため、全体の安全性が確保できます。

4. SupervisorJob / supervisorScope による部分失敗許容パターン

基本的な使い方

出力例

UI での実装例(ViewModel)

バックグラウンドバッチ処理の例


5. Kotlin 1.9 の runBlocking 改善とテスト戦略

改善点(公式リリースノート参照)

Kotlin 1.9 では runBlocking がキャンセル伝搬を即時に行うよう内部実装が変更 されました(Kotlin 1.9 Release Notes – Coroutines)。これにより、テストや CLI ツールで runBlocking が途中でキャンセルされた際に残存ジョブが残り続けるリスクが大幅に低減されます。

実務向けテスト例 – runTest + Turbine

CI で安定させるコツ

  1. ディスパッチャは明示的に指定
    runTest { dispatcher = Dispatchers.IO } のように本番と同じディスパッチャを使用すると、環境差異が減ります。
  2. 仮想時間の制御
    advanceUntilIdle() を使ってタイマーや遅延を即座に進め、テスト実行時間を短縮します。
  3. 例外検証は統一
    assertFailsWith<Exception> と Turbine の awaitError() を組み合わせると、型・メッセージの両方を確実にチェックできます。

6. 記事の要点まとめ

  • 例外伝搬は子 → 親へ自動で流れ、SupervisorJob と併用すれば失敗が他タスクに波及しません。
  • launch は内部で try/catch もしくは CoroutineExceptionHandler を必ず設定し、asyncawait() で例外取得を徹底します。
  • ベストプラクティスSupervisorJob + CoroutineExceptionHandler の組み合わせで未捕捉例外を一元管理。
  • UI 層はハンドラ+Snackbar 等でユーザーに即時フィードバック、Repository は retryWhen と指数バックオフで自動リトライ、バッチ処理は supervisorScope で部分失敗許容し個別ロギングを行います。
  • Kotlin 1.9 の runBlocking 改善によりテストや CLI ツールの安定性が向上。runTest と Turbine を活用すれば例外シナリオも deterministic に検証可能です。

これらのパターンを自プロジェクトに組み込めば、クラッシュや予期せぬエラーによるユーザー体験の低下を防止しつつ、保守性・可観測性に優れたコードベースが実現できます。

スポンサードリンク

もっとスキルを活かしたいエンジニアへ

スポンサードリンク
働き方から選べる

無料で使えて良質な案件の情報収集ができるサービス

エンジニアの世界では、「いつでも動ける状態を作っておけ」とよく言われます。
技術やポートフォリオがあっても、自分に合う案件情報を日常的に見れていないと、いざ動こうと思った時に比較や判断が難しくなってしまいます。
普段から案件情報が集まる環境を作っておくと、良い案件が出た時にすぐ動きやすくなりますよ。
筆者自身も、メガベンチャー勤務時代に年収1,500万円を超えた経験があります。振り返ると、技術だけでなく「どんな案件や働き方があるか」を日頃から見ていたことが、キャリアの選択肢を広げるきっかけになりました。
このブログを読んでくれた方に感謝を込めて、実際に使っている情報収集サービスを紹介します。

フルリモート・週3日・高単価、どんな条件も妥協したくないなら

フリーランスボードに無料会員登録する

利用者10万人以上。業界最大規模45万件の案件。AIマッチ機能や無料の相場情報が人気。

年収800万円以上のキャリアアップ・ハイクラス正社員を視野に入れているなら

Beyond Careerに無料相談する

内定獲得率90%以上。紹介先企業とは役員クラスのコネクションがある安心と信頼できるエージェント。


-Kotlin