◉RORK LABEN
●EXPO — EAS Observe がネイティブクラッシュも記録(10/07)。SDK 57 は 57.0.21 以降で確認できます●SDK 58 — SDK 58 Beta は 9/15 公開。stable の日付はまだ未確認です●RN 0.88 — React Native 0.88.x の正式リリース予定は 10/12、残り3日●Q&A — expo-widgets が本番ビルドだけ真っ黒になる、という問いが出ています●RORK — 09-29 に GPT-6.1 Sol を追加。Pro・Max プランで利用できます●NEW — クライアントのアプリを作る前に決める、公開アカウントの持ち主●EXPO — EAS Observe がネイティブクラッシュも記録(10/07)。SDK 57 は 57.0.21 以降で確認できます●SDK 58 — SDK 58 Beta は 9/15 公開。stable の日付はまだ未確認です●RN 0.88 — React Native 0.88.x の正式リリース予定は 10/12、残り3日●Q&A — expo-widgets が本番ビルドだけ真っ黒になる、という問いが出ています●RORK — 09-29 に GPT-6.1 Sol を追加。Pro・Max プランで利用できます●NEW — クライアントのアプリを作る前に決める、公開アカウントの持ち主
記事一覧/開発ツール
⬡ 開発ツール/2026-07-10上級

クラッシュとして記録されない強制終了 — Rork アプリの JetsamEvent を読む

Crashlytics には何も出ていないのにレビューで「勝手に閉じる」と書かれる。その多くはメモリ超過による OS からの強制終了です。JetsamEvent レポートの読み方と、画像中心アプリのメモリ上限を実測から設計する手順をまとめます。

Rork577Rork Max235メモリ4iOS114個人開発215

✦ プレミアム記事

App Store のレビュー欄に「開いてしばらくすると勝手に閉じます」と書かれていたのに、Crashlytics のダッシュボードは静まり返ったまま、という時期がありました。壁紙アプリの一つで、しかも再現手順が「たくさんスクロールする」としか書かれていない。手元の実機ではどれだけ触っても落ちません。

原因が分かったのは、実機の「設定 > プライバシーとセキュリティ > 解析および改善 > 解析データ」を開いて、JetsamEvent-2026-… という名前のファイルが並んでいるのを見つけたときでした。クラッシュではなく、OS がメモリ不足を理由にアプリを終了させていた。だからクラッシュレポータには何も届いていなかったのです。

Rork や Rork Max で作ったアプリでも、事情はまったく同じです。生成されたコードがどれだけ整っていても、iOS がプロセスに与えるメモリの上限は変わりません。むしろ生成コードは画像やリストを気前よく扱うことが多く、この上限に触れやすい傾向があると私自身は感じています。

Jetsam はクラッシュではない、という前提

iOS には Jetsam という仕組みがあります。システム全体のメモリが逼迫したとき、あるいは単一プロセスが device ごとの上限を超えたとき、カーネルがそのプロセスに SIGKILL を送って回収します。

SIGKILL はハンドルできません。ここが重要な点です。Crashlytics も Sentry も、シグナルハンドラや例外ハンドラを仕込んでクラッシュを捕まえます。捕まえる隙を与えずに殺されるので、クラッシュとして記録されない。App Store Connect の「クラッシュ」指標にも現れません。

代わりに、Xcode Organizer では Crashes ではなく Disk Writes / Hangs とは別枠の、MXAppExitMetric の cumulativeMemoryResourceLimitExitCount として集計されます。ここを見ていない個人開発者は多いはずです。私も見ていませんでした。

終了の種類クラッシュレポータに届くか確認場所
例外・シグナル(SIGSEGV 等)届くCrashlytics / Organizer > Crashes
メモリ超過(Jetsam)届かない実機の解析データ / MetricKit
ウォッチドッグ(起動遅延)一部届くOrganizer > Hangs、0x8badf00d
バックグラウンドでの回収届かない正常動作。対処不要

最下段が地味に大切です。段階的な解放設計そのものはiOS のメモリ逼迫に応じて 5 段階で解放する設計で整理しました。バックグラウンドに回ったアプリが後で回収されるのは、iOS の正常な振る舞いです。すべての JetsamEvent を潰そうとすると、無駄な作業に沈みます。潰すべきは フォアグラウンドで殺されたもの だけです。

JetsamEvent レポートを読む

実機の解析データからファイルを取り出します。共有ボタンから AirDrop や Files に出せます。中身は JSON 風のテキストです。

まず 1 行目付近のヘッダを見ます。

{"bug_type":"298","timestamp":"2026-06-14 21:03:11.42 +0900","os_version":"iPhone OS 26.1 (23B82)",
 "incident_id":"…","pageSize":16384,"memoryStatus":{"compressorSize":98213,"memoryPages":{"active":41022,
 "free":1290,"wired":38310}}}

bug_type が 298 なら Jetsam です。そして pageSize が 16384、つまり 16 KB。ここを 4096 だと思い込むと、以降の換算が 4 倍ずれます。A14 以降の端末は 16 KB ページなので、必ずこのフィールドを読んでください。

次に、殺された当人を探します。レポート本体は states の配列で、各プロセスがこう並びます。

{"uuid":"…","states":["frontmost"],"killDelta":0,"genCount":0,"age":133,"purgeable":0,
 "fds":124,"coalition":312,"rpages":86214,"reason":"per-process-limit",
 "name":"WallpaperApp","cpuTime":41.2,"idleDelta":0}

読むべきは 3 つです。

  1. states に frontmost が含まれるか — 含まれていれば、ユーザーの目の前で消えたということです
  2. reason — per-process-limit は自分のアプリが上限を超えた、vm-pageshortage はシステム全体の逼迫に巻き込まれた
  3. rpages — 常駐ページ数。MB への換算は rpages × pageSize ÷ 1024 ÷ 1024

この例なら 86214 × 16384 ÷ 1048576 ≒ 1,347 MB。iPhone SE(第3世代)で 1,384 MB の上限に触れて殺された、という読み方になります。

面倒なので、一括で換算するスクリプトを置いておきます。

#!/usr/bin/env bash
# jetsam-summary.sh — 解析データから取り出した .ips をまとめて要約する
# 使い方: ./jetsam-summary.sh ~/Downloads/JetsamEvent-*.ips
for f in "$@"; do
  python3 - "$f" <<'PY'
import json, sys, re
raw = open(sys.argv[1], encoding="utf-8").read()
# 先頭ヘッダ行と本体が連結されているので、最初の } で分割する
head, body = raw.split("\n", 1) if "\n" in raw else (raw, "{}")
page = json.loads(head).get("pageSize", 4096)
ts   = json.loads(head).get("timestamp", "?")
for m in re.finditer(r'\{"uuid".*?\}', body):
    p = json.loads(m.group(0))
    mb = p.get("rpages", 0) * page / 1048576
    if p.get("reason") in ("per-process-limit", "vm-pageshortage") and mb > 100:
        front = "FRONTMOST" if "frontmost" in p.get("states", []) else "background"
        print(f'{ts}  {p["name"]:<22} {mb:8.1f} MB  {p["reason"]:<18} {front}')
PY
done

私はこれを 3 週間分のレポート 41 件に流し、フォアグラウンドで per-process-limit に触れていたのが 12 件、うち 11 件が同じ画面(グリッド表示の壁紙一覧)だと分かりました。ここまで来れば、あとは実装の問題です。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦JetsamEvent レポートの rpages を MB に換算し、どのプロセスが何 MB で殺されたかを特定する手順
✦os_proc_available_memory() で残メモリを実測し、iPhone SE 実機で 1,384 MB / 2,099 MB の上限差を確認したログ
✦画像キャッシュを totalCostLimit で残メモリの 25% に自動追従させる Swift / React Native 両方の実装
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

⬡ 開発ツール2026-05-18
Rork で作った iOS アプリを iPhone Air と 17 Pro シリーズに対応させる — 2026年の解像度ごとのレイアウト調整パターン
iPhone Air・17 Pro・17 Pro Max の新解像度で既存 Rork アプリのレイアウトが崩れる問題を、4本の iOS アプリを並行更新した経験から解説。解像度定数管理・Safe Area・壁紙フルスクリーン表示の具体的な実装パターンを示します。
⬡ 開発ツール2026-09-21
exit code 0 で止まるビルド — ログを黙らせていた設定と、空ファイルを通した存在チェック
eas build --local が exit code 0 but produced no further output で止まる件と、0 バイトのスタブが埋め込まれず dyld で落ちる件。どちらも原因は出力を減らす設定でした。自分のスクリプトを棚卸しする手順まで書き残します。
⬡ 開発ツール2026-09-19
Rork が書き換えた箇所だけを読む — 再エクスポートのたびに回している差分確認の手順
再エクスポートしたコードを前回との差分として読むための手順です。追跡ファイルを一度消してから重ねる、雑音を外して数える、合流の前に一度止める——この3つで上書き事故を止めています。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます