MacBookが強制終了した原因でClaudeアプリが大量のスワップファイルを作っていた

  • MacBookが突然再起動してしまいました。
  • 原因を調べたら、Claudeアプリがメモリリークしていたのか、スワップファイルが11GBも蓄積していました。
  • Cmd+Qで完全終了したらスワップ使用領域がみるみる減りました。
  • Electronアプリは定期的に再起動が必要ですね

メモリ不足で突然の再起動に遭遇

Google Chromeで画像検索をしていたら、特に重い処理をしていたわけでもなく、急にメモリ不足になりました。

アプリを強制終了しようとしても応答せず、作業中のMacBook Airが突然強制終了になりました。

システムログから読み取れる直接の原因(watchdog, remoted)

再起動後に表示されたエラーダイアログには、システムの問題レポートが表示されていました。

macOSが生成した問題レポートには、次のメッセージが記録されていました。

panic(cpu 2 caller 0xffffff801b2b289b): userspace watchdog timeout: 
no successful checkins from remoted (2 induced crashes) in 180 seconds
Code language: JavaScript (javascript)

これは「watchdog timeout」と呼ばれる現象です1。watchdogはシステムの監視機能で、重要なプロセスが一定時間応答しなくなると、システム全体の安定性を保つために強制的に再起動を実行します。まるで番犬が異常を察知して警報を鳴らすようなものです。今回応答しなくなったのはremotedというプロセスで、画面共有やリモートアクセス機能を担当しています。

メモリ不足を示すスワップファイルの痕跡

しかし、このプロセス自体に問題があったわけではありません。問題レポートをさらに詳しく見ると、メモリ不足を示す兆候が見つかりました。

Compressor Info: 21% of compressed pages limit (OK) and 52% of segments limit (OK) 
with 11 swapfiles and LOW swap space
Code language: JavaScript (javascript)

11 swapfiles」という記載は異常です。
macOSはメモリ不足時に仮想メモリとしてディスク領域を使用しますが、通常は1〜2個のスワップファイルで済みます2メモリ不足が深刻になると、システムは段階的に追加のスワップファイルを作成します。11個も作られているということは、長期間にわたって深刻なメモリ不足状態が続いていたことを示しています。

アクティビティモニタの「メモリプレッシャー」

不具合の時のアクティビティモニタを写真で確認すると、以下の状況でした。

アクティビティモニタでメモリプレッシャーが黄色や赤色になったときは要注意です。個別のプロセス数値よりも、システム全体のメモリプレッシャーグラフが重要な指標となります。

  • メモリプレッシャー:赤色(危険レベル)
  • 物理メモリ:16GB
  • 使用済みメモリ:15.92GB(99.5%使用)
  • スワップ使用領域:11.00GB

つまり、物理メモリ16GBがフルに使われ、さらにディスク上に11GBの仮想メモリ領域が確保された状態でした。システム全体では27GBの仮想メモリ空間を使用していたことになります。この状況では、メモリアクセスの大部分がディスクI/Oを伴うため、システム全体のパフォーマンスが著しく低下します。その結果、remotedプロセスが適切に応答できなくなり、watchdog timeoutが発生したと考えられます。

プロセス別のメモリ使用量(占有メモリと共有メモリ)

興味深いことに、アクティビティモニタに表示される各プロセスのメモリ使用量を合計しても、実際の使用メモリ量には達しません。これは、システムアーキテクチャに起因する現象です。

アクティビティモニタでプロセス別のメモリ使用量を確認すると、以下のような結果が得られました。

  • Claude Helper (Renderer): 874MB
  • WindowServer: 735MB
  • kernel_task: 568MB(システム保護のため意図的に増加)
  • Slack Helper (Renderer): 509MB
  • Finder: 310MB
  • Google Chrome: 261MB

アクティビティモニタは各プロセスの「専有メモリ」を表示しますが、実際のシステムでは以下のメモリ領域が共有されるか、別途計上されます3

  • 共有ライブラリやフレームワーク
  • カーネルメモリ領域
  • GPUメモリとそのバッファ
  • ファイルシステムキャッシュ
  • ネットワークバッファ

特にスワップファイル11GBは、プロセス一覧には表示されない仮想メモリ使用量でした4

システムの保護モードの表れ(kernel_task)

中でも、kernel_taskの568MBという数値は注目すべき点です。

kernel_taskは、システムが熱暴走やメモリ不足を検出したときに、意図的にCPU使用率を上げてシステム全体の処理速度を下げる保護機能を持ちます。つまり、この数値の高さは、システムが保護モードに入っていたことを示しています。

「Claude Helper (Renderer)」とElectron

この中で特に異常なのは「Claude Helper (Renderer)」と「Slack Helper (Renderer)」で、メモリリークが疑われます。

ClaudeとSlack、あるいはVS CodeなどはElectronで開発されたアプリケーションです。

ElectronアプリとHelper (Renderer)プロセス Electronとは Chromium ブラウザエンジン + Node.js ランタイム = Electron デスクトップアプリ マルチプロセスアーキテクチャ メインプロセス アプリ全体の管理 ウィンドウ作成 システムAPI レンダラープロセス Webページ描画 JavaScript実行 Helper (Renderer) = レンダラープロセス ClaudeやSlackの UI処理を担当 本質的にはブラウザを内蔵したアプリケーション → メモリリークが発生しやすい構造

Electronは、ChromiumブラウザエンジンとNode.jsランタイムを組み合わせたクロスプラットフォーム開発フレームワークで、Web技術を使ってデスクトップアプリを構築できます。Electronアプリは、メインプロセスと複数のレンダラープロセスからなるマルチプロセスアーキテクチャを採用しています。

Helper (Renderer)プロセスは、このレンダラープロセスに相当し、Webページの描画とJavaScript実行を担当します。

デスクトップアプリとウェブページの違い

Webアプリケーションは本来、ページをリロードするとメモリがリセットされる前提で設計されています。

Electronアプリでメモリリークが起きやすい理由 長時間稼働による蓄積 Webアプリ前提設計 ページリロードで メモリリセット 数日間連続稼働 排水機能が追いつかない 複数コンテキスト管理 Slack複数ワークスペース 使わないものも メモリ消費継続 Claude長い会話履歴 複雑なレンダリング要素蓄積 ガベージコレクション限界 V8エンジン使用 一般的に効率的 回収されない要因 ・クロージャ ・循環参照 DOM要素とJavaScriptオブジェクト間の相互参照 DOM要素 JavaScriptオブジェクト → ガベージコレクション阻害 適切に解放されずメモリ使用量が徐々に増加

しかし、デスクトップアプリとして数日間動作し続けると、JavaScriptのオブジェクトやDOMエレメントが適切に解放されずに蓄積されます。特に、Slackのように複数のワークスペースを管理するアプリでは、使っていないワークスペースでもメモリを消費し続けます。Claudeでも長い会話履歴や複雑なレンダリング要素が蓄積されます。

  • 長時間稼働による蓄積
  • 複数のコンテキスト管理
  • ガベージコレクションの限界

ElectronアプリはV8 JavaScriptエンジンを使用しており、V8のガベージコレクションは一般的に効率的です。しかし、クロージャによる変数の保持、循環参照、大きなオブジェクトの長期保持などにより、一部のメモリ領域が適切に回収されない場合があります。特に、DOM要素とJavaScriptオブジェクト間の相互参照は、ガベージコレクションを阻害する要因となりやすいです5

ElectronアプリはCommand+Qで完全に終了する

重要なのは、ElectronアプリやブラウザをCommand+Qで完全に終了させることです。

ウィンドウを閉じるだけでは、アプリは裏で動作しメモリを消費し続けます。週に1〜2回は再起動すると、蓄積されたメモリリークをリセットできます。また、SlackやClaude、Visual Studio Codeなど、複数のElectronアプリを同時に長時間使用することは避けます。

たとえば、Claudeを「完全終了」すると、みるみるメモリプレッシャーが下がりました。

急に気になったので、もしかするとClaudeのサーバ負荷軽減のために、ローカルメモリを使うようにしているのかな、と思いました。

ブラウザの画像処理

メモリ不足の最終的な引き金となったのは、Google Chromeでの画像検索でした。すでにメモリ使用量が限界に近い状況で、さらに負荷をかけたことでシステムが破綻しました。

99.5% ブラウザの画像処理が最後の一押し すでにメモリ使用量が限界に近い状況 Google画像検索がトドメを刺した 画像検索の大量消費理由 一度に数百枚の画像表示 スクロールで追加読み込み 高解像度画像も含む メモリ使用量急激増加 プリロード機能の影響 関連ページの先読み 実際にクリックする前に ページデータを読み込み 想定以上のメモリ消費 設定でオフにすることが可能 見えないメモリ消費の仕組み アクティビティモニタの落とし穴 各プロセスの合計 ≠ 実際の使用量 隠れたメモリ領域 ・共有ライブラリ ・カーネルメモリ ・GPUメモリ ・ファイルキャッシュ

一度に数百枚の画像を表示し、スクロールするたびに新しい画像を読み込みます。さらに、Chromeの「ページをプリロードする」機能が有効になっていると、関連ページを先読みしてメモリ使用量がさらに増加します。

ブラウザ設定の最適化

  • Memory Saver機能の活用
  • プリロード機能の無効化
  • タブ管理の徹底
  • Chromeには「Memory Saver」機能が搭載されています。使っていないタブを自動的に休止状態にして、メモリ使用量を削減します。
  • Chromeの設定で「ページをプリロードする」機能を無効にします。これにより、不要な先読み処理を防いでメモリ使用量を削減できます。
  • ブラウザのタブは10個以下に抑えます。特に画像検索後はすぐにタブを閉じると、キャッシュされた画像データによるメモリ消費を防げます。

とくに大事なのは「ページをプリロードする」機能の無効です。画像検索では、不要な先読み処理によって、大量のメモリを消費していました。

再起動後の改善効果

システム再起動後のメモリ使用状況は劇的に改善されました。

  • Claude Helper (Renderer): 874MB → 228MB(74%減少)
  • Slack Helper (Renderer): 509MB → 323MB(37%減少)
  • スワップ使用量: 11.00GB → 0バイト(完全解消)
  • メモリプレッシャー: 赤色 → 緑色

この結果から、Electronアプリのメモリリークとスワップファイルの蓄積が、いかに深刻な問題だったかが分かります。

まとめ

MacBookの突然の再起動は、Electronアプリの長期間使用によるメモリリークと、ブラウザの画像処理負荷が組み合わさって発生しました。根本的な原因はwatchdog timeoutではなく、深刻なメモリ不足状態でした。ElectronアプリとWebブラウザの定期的な再起動、適切な設定変更、使用習慣の見直しにより、同様の問題を予防できます。システム全体のメモリプレッシャー監視と、見えないスワップファイル蓄積への注意が重要です。

MacBook突然再起動の原因と対策 問題:watchdog timeout MacBookが突然再起動 システムログにwatchdog timeout 物理メモリ16GB 使用済み15.92GB (99.5%) スワップ11GB発生 原因:Electronアプリのメモリリーク Claude Helper: 874MB Slack Helper: 509MB 長時間稼働による蓄積 ガベージコレクション限界 画像検索が最後の引き金 対策と予防 定期的再起動 Cmd+Q で完全終了 週1-2回推奨 ウィンドウ閉じるのみはNG ブラウザ設定 プリロード機能OFF Memory Saver ON タブ10個以下に制限 監視方法 メモリプレッシャー確認 赤色は危険信号 個別数値より全体重視 改善効果 Claude: 874→228MB Slack: 509→323MB スワップ: 11GB→0GB 続ける
  1. Reducing Slack’s memory footprint – Engineering at Slack – Slack公式によるElectronアプリのメモリ使用量問題と対策に関する技術解説
  2. Code Helper (Renderer) memory leak · Issue #105516 · microsoft/vscode – Visual Studio CodeのRendererプロセスメモリリーク問題についてのGitHub Issue
  3. Overcoming Memory Issues in Electron Desktop Apps – Electronアプリケーションのメモリ管理問題と最適化手法についての包括的ガイド
  4. Debugging Electron Memory Usage | Seena Burns – Electronアプリのメモリ使用量をデバッグする実践的な方法論
  5. Memory management for complex apps (Renderer process goes low on memory and crashes eventually) · Issue #7010 · electron/electron – Electron公式リポジトリでの複雑なアプリのメモリ管理問題についての議論
  6. Creating a Slack app that uses fewer resources – Slackアプリのリソース使用量を削減する代替実装についての技術的考察
  7. Figma Helper (Renderer) is using excessive memory, why? | Figma Forum – FigmaのRendererプロセスメモリ使用量問題に関するユーザーコミュニティでの議論

  1. watchdog timeoutは、macOSでシステムの安定性を保つ重要な機能です。重要なプロセスが応答しない場合、システム全体をクラッシュから守るために強制的に再起動を実行します。 – How to Fix Watchdog Timeout Kernel Panic on Mac – AppleToolBox
  2. macOSのスワップメモリは動的に管理され、通常の使用では少数のスワップファイルで済みますが、深刻なメモリ不足時には複数のファイルが作成されます。 – How Much Swap Memory Is Mac Using
  3. システム全体のメモリ使用量と個別プロセスの合計が一致しないのは、共有ライブラリ、カーネルメモリ、GPUメモリなどが共有されるためです。 – How to properly debug Electron memory issues?
  4. macOSのスワップファイルは /private/var/vm ディレクトリに swapfile0, swapfile1 という名前で保存され、アクティビティモニタの個別プロセス表示には含まれません。 – What is swap used in Mac Activity Monitor? | Digital Trends
  5. Electronアプリでは、イベントリスナーの適切な削除、循環参照の回避、グローバル変数の制限が重要です。これらの要因がメモリリークの主な原因となります。 – Memory Leaks in Electron application