Skip to content

Add com.codename1.crash on-device crash protection client#5001

Open
shai-almog wants to merge 4 commits into
masterfrom
add-crash-protection
Open

Add com.codename1.crash on-device crash protection client#5001
shai-almog wants to merge 4 commits into
masterfrom
add-crash-protection

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

Summary

  • New com.codename1.crash package — CrashProtection, PiiScrubber (public, subclassable), CrashReportPayload. Storage-first delivery: every payload is written to Storage with a fresh eventId before the POST; the storage entry is deleted only on a 2xx response. Failed sends are retried on the next launch and the server dedups via the same eventId.
  • Default PiiScrubber rules: emails partially redacted (keep first 3 chars of local part + full domain, e.g. joe***@example.com); runs of 6+ consecutive digits collapsed to [num]; URLs are NOT scrubbed. App devs override scrubMessage / scrubFrame and register via CrashProtection.setScrubber(...).
  • Endpoint URL is fixed to https://cloud.codenameone.com/api/v2/crash/reports. Opt-in is developer-controlled via setEnabled(boolean) (persisted in Preferences, default off). Simulator skips uploads.
  • Wire-up: Android UncaughtExceptionHandler now forwards to CrashProtection.capture(e) alongside the legacy Log.bindCrashProtection path (guarded by try/catch so a bug here can't suppress the legacy path). iOS needs no client change — existing signal handlers already convert signals into JVM exceptions that flow through the EDT error handler.
  • Build-server helper: com.codename1.builders.util.CrashSymbolUploader is a standalone (no Spring) multipart-POST utility the cloud build executor calls after a successful release build to ship mapping.txt (Android) or the dSYM zip (iOS) to the matching server endpoint. AndroidGradleBuilder + IPhoneBuilder carry hook-point comments showing the executor where to call it.

Pairs with codenameone/BuildCloud's server PR adding the matching endpoints, entities, and migration.

Test plan

  • CN1 PR-CI doc validator (validate-java25-markdown-docs.sh) passes — all crash code uses /// markdown style, no classic /** Javadoc.
  • mvn compile succeeds on Java 8 / 17 / 21 matrix (core module enforces Java 5 source/target).
  • Maven plugin module compiles with the new CrashSymbolUploader utility.
  • tests/core PiiScrubberTest covers: email partial redaction, short local-part handling, digit-run scrubbing, URL pass-through, subclass override on top of defaults, null in / null out.
  • On-device sanity: build a sample app, call CrashProtection.install() + setEnabled(true), trigger an NPE, verify a CN1Crash__$<eventId> storage entry is created, then deleted after a successful POST to the cloud endpoint.
  • Confirm the legacy Log.bindCrashProtection path still works when both systems are installed (the Android handler runs both branches, guarded).

🤖 Generated with Claude Code

New package for capturing unhandled exceptions on device, scrubbing
PII, and uploading structured crash reports to the BuildCloud crash
service. Pairs with the new /api/v2/crash/reports server endpoint
(separate BuildCloud PR).

Surface:
- CrashProtection.install() / setEnabled() / setScrubber() /
  capture(). Endpoint is fixed; opt-in is developer-controlled and
  persisted in Preferences (default off).
- PiiScrubber is a public subclassable class. Default rules: emails
  partially redacted (keep first 3 chars + full domain), runs of 6+
  digits collapsed to [num]. URLs are NOT scrubbed.
- Storage-first delivery: every payload is written to Storage with a
  fresh eventId BEFORE the POST; the storage entry is deleted only on
  a 2xx. Failed sends are retried on next launch. The server uses
  eventId for idempotent dedup.

Wire-up:
- Android: AndroidImplementation's UncaughtExceptionHandler now also
  forwards to CrashProtection.capture(e), guarded by try/catch so a
  bug here can't suppress the legacy Log.bindCrashProtection path.
- iOS: no client change. The existing signal handlers in
  CodenameOne_GLAppDelegate.m convert signals to JVM exceptions which
  flow through the EDT error handler naturally.

Build-server utility:
- maven/codenameone-maven-plugin/.../util/CrashSymbolUploader. Used by
  the cloud build executor's post-build hook to POST mapping.txt
  (Android) or the dSYM zip (iOS, release builds only) to the
  /api/v2/build/{buildKey}/symbols endpoint. Standalone, no Spring dep.
  AndroidGradleBuilder + IPhoneBuilder carry comments pointing the
  executor at the right call sites.

Java 5 source compatibility maintained in the core client classes.
No new runtime dependencies on the device. ASCII-only sources;
CodenameOne header (not Oracle).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shai-almog

shai-almog commented May 22, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 121 screenshots: 121 matched.
✅ JavaScript-port screenshot tests passed.

@shai-almog

shai-almog commented May 22, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 128 screenshots: 128 matched.

Native Android coverage

  • 📊 Line coverage: 14.18% (8633/60880 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 11.48% (42528/370332), branch 5.03% (1752/34839), complexity 6.04% (2017/33383), method 10.51% (1639/15601), class 17.13% (377/2201)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 14.18% (8633/60880 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 11.48% (42528/370332), branch 5.03% (1752/34839), complexity 6.04% (2017/33383), method 10.51% (1639/15601), class 17.13% (377/2201)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 140ms / native 243ms = 0.5x speedup
SIMD float-mul (64K x300) java 289ms / native 117ms = 2.4x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 340.000 ms
Base64 CN1 decode 237.000 ms
Base64 native encode 1041.000 ms
Base64 encode ratio (CN1/native) 0.327x (67.3% faster)
Base64 native decode 1198.000 ms
Base64 decode ratio (CN1/native) 0.198x (80.2% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog

shai-almog commented May 22, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 128 screenshots: 128 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 285 seconds

Build and Run Timing

Metric Duration
Simulator Boot 69000 ms
Simulator Boot (Run) 1000 ms
App Install 21000 ms
App Launch 11000 ms
Test Execution 268000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 66ms / native 3ms = 22.0x speedup
SIMD float-mul (64K x300) java 67ms / native 3ms = 22.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 328.000 ms
Base64 CN1 decode 477.000 ms
Base64 native encode 1056.000 ms
Base64 encode ratio (CN1/native) 0.311x (68.9% faster)
Base64 native decode 409.000 ms
Base64 decode ratio (CN1/native) 1.166x (16.6% slower)
Base64 SIMD encode 143.000 ms
Base64 encode ratio (SIMD/CN1) 0.436x (56.4% faster)
Base64 SIMD decode 89.000 ms
Base64 decode ratio (SIMD/CN1) 0.187x (81.3% faster)
Base64 encode ratio (SIMD/native) 0.135x (86.5% faster)
Base64 decode ratio (SIMD/native) 0.218x (78.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 27.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.074x (92.6% faster)
Image applyMask (SIMD off) 193.000 ms
Image applyMask (SIMD on) 257.000 ms
Image applyMask ratio (SIMD on/off) 1.332x (33.2% slower)
Image modifyAlpha (SIMD off) 227.000 ms
Image modifyAlpha (SIMD on) 50.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.220x (78.0% faster)
Image modifyAlpha removeColor (SIMD off) 185.000 ms
Image modifyAlpha removeColor (SIMD on) 221.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.195x (19.5% slower)

@shai-almog

shai-almog commented May 22, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 124 screenshots: 124 matched.
✅ Native iOS screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 274 seconds

Build and Run Timing

Metric Duration
Simulator Boot 79000 ms
Simulator Boot (Run) 1000 ms
App Install 14000 ms
App Launch 7000 ms
Test Execution 299000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 80ms / native 3ms = 26.6x speedup
SIMD float-mul (64K x300) java 105ms / native 5ms = 21.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 591.000 ms
Base64 CN1 decode 212.000 ms
Base64 native encode 646.000 ms
Base64 encode ratio (CN1/native) 0.915x (8.5% faster)
Base64 native decode 548.000 ms
Base64 decode ratio (CN1/native) 0.387x (61.3% faster)
Base64 SIMD encode 56.000 ms
Base64 encode ratio (SIMD/CN1) 0.095x (90.5% faster)
Base64 SIMD decode 48.000 ms
Base64 decode ratio (SIMD/CN1) 0.226x (77.4% faster)
Base64 encode ratio (SIMD/native) 0.087x (91.3% faster)
Base64 decode ratio (SIMD/native) 0.088x (91.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 24.000 ms
Image createMask (SIMD on) 14.000 ms
Image createMask ratio (SIMD on/off) 0.583x (41.7% faster)
Image applyMask (SIMD off) 282.000 ms
Image applyMask (SIMD on) 84.000 ms
Image applyMask ratio (SIMD on/off) 0.298x (70.2% faster)
Image modifyAlpha (SIMD off) 68.000 ms
Image modifyAlpha (SIMD on) 41.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.603x (39.7% faster)
Image modifyAlpha removeColor (SIMD off) 65.000 ms
Image modifyAlpha removeColor (SIMD on) 82.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.262x (26.2% slower)

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog

shai-almog commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 128 screenshots: 128 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 171 seconds

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 66ms / native 7ms = 9.4x speedup
SIMD float-mul (64K x300) java 58ms / native 3ms = 19.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 307.000 ms
Base64 CN1 decode 207.000 ms
Base64 native encode 825.000 ms
Base64 encode ratio (CN1/native) 0.372x (62.8% faster)
Base64 native decode 441.000 ms
Base64 decode ratio (CN1/native) 0.469x (53.1% faster)
Base64 SIMD encode 66.000 ms
Base64 encode ratio (SIMD/CN1) 0.215x (78.5% faster)
Base64 SIMD decode 49.000 ms
Base64 decode ratio (SIMD/CN1) 0.237x (76.3% faster)
Base64 encode ratio (SIMD/native) 0.080x (92.0% faster)
Base64 decode ratio (SIMD/native) 0.111x (88.9% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 22.000 ms
Image createMask (SIMD on) 6.000 ms
Image createMask ratio (SIMD on/off) 0.273x (72.7% faster)
Image applyMask (SIMD off) 93.000 ms
Image applyMask (SIMD on) 86.000 ms
Image applyMask ratio (SIMD on/off) 0.925x (7.5% faster)
Image modifyAlpha (SIMD off) 145.000 ms
Image modifyAlpha (SIMD on) 88.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.607x (39.3% faster)
Image modifyAlpha removeColor (SIMD off) 110.000 ms
Image modifyAlpha removeColor (SIMD on) 81.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.736x (26.4% faster)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant