Skip to content

Fix StackOverflowError in Display.setCurrent off-EDT (#4811)#4812

Merged
shai-almog merged 1 commit into
masterfrom
fix-4811-setcurrent-stack-overflow
Apr 25, 2026
Merged

Fix StackOverflowError in Display.setCurrent off-EDT (#4811)#4812
shai-almog merged 1 commit into
masterfrom
fix-4811-setcurrent-stack-overflow

Conversation

@liannacasper
Copy link
Copy Markdown
Collaborator

Summary

  • Fixes stack overflow in edt #4811Display.setCurrent invoked from a non-EDT thread recursed infinitely into callSerially -> RunnableWrapper.run -> setCurrent until the JVM stack overflowed (the SOH happened to surface in getDefaultVirtualKeyboard/setShowVirtualKeyboard because those frames sit on top of the loop).
  • Root cause: when codenameOneRunning is false (e.g. before init has fully completed or after deinitialize), callSerially falls back to executing the runnable synchronously on the calling thread, which re-enters setCurrent in the same off-EDT state.
  • Move the !isEdt() dispatch ahead of any UI work in setCurrent (so VKB folding, revalidate/repaint, and editing-text branches always execute on the EDT) and fail fast with a clear IllegalStateException when the EDT cannot accept the call.

Test plan

  • mvn -pl core compile -Plocal-dev-javase succeeds (verified locally).
  • Existing JavaSE tests pass (ant test-javase / mvn test -Plocal-dev-javase).
  • Manual: invoking Display.getInstance().setCurrent(form, false) from a background thread before init (or after deinitialize) now throws IllegalStateException with a clear message instead of crashing with StackOverflowError.
  • Normal off-EDT setCurrent calls (during a running app) continue to dispatch through callSerially and show the form.

🤖 Generated with Claude Code

When setCurrent was invoked from a non-EDT thread while Codename One
was not running, callSerially's synchronous fallback re-entered
setCurrent on the same thread and recursed until the stack overflowed.
Move the EDT dispatch ahead of the UI work and fail fast with a clear
IllegalStateException when the EDT cannot accept the call.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ByteCodeTranslator: 0 findings (no issues)
    • android: 0 findings (no issues)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 0 findings (no issues)
  • PMD: 0 findings (no issues) [Report archive]
  • Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

@shai-almog
Copy link
Copy Markdown
Collaborator

shai-almog commented Apr 25, 2026

Compared 37 screenshots: 37 matched.

Native Android coverage

  • 📊 Line coverage: 7.94% (4213/53043 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 6.22% (20744/333558), branch 3.03% (976/32174), complexity 3.70% (1137/30766), method 6.50% (933/14344), class 10.68% (203/1900)
    • 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: 7.94% (4213/53043 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 6.22% (20744/333558), branch 3.03% (976/32174), complexity 3.70% (1137/30766), method 6.50% (933/14344), class 10.68% (203/1900)
    • 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
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 747.000 ms
Base64 CN1 encode 174.000 ms
Base64 encode ratio (CN1/native) 0.233x (76.7% faster)
Base64 native decode 1129.000 ms
Base64 CN1 decode 292.000 ms
Base64 decode ratio (CN1/native) 0.259x (74.1% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog
Copy link
Copy Markdown
Collaborator

shai-almog commented Apr 25, 2026

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 91000 ms
Simulator Boot (Run) 2000 ms
App Install 17000 ms
App Launch 9000 ms
Test Execution 158000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 2344.000 ms
Base64 CN1 encode 1599.000 ms
Base64 encode ratio (CN1/native) 0.682x (31.8% faster)
Base64 native decode 1404.000 ms
Base64 CN1 decode 1414.000 ms
Base64 decode ratio (CN1/native) 1.007x (0.7% slower)
Base64 SIMD encode 571.000 ms
Base64 encode ratio (SIMD/native) 0.244x (75.6% faster)
Base64 encode ratio (SIMD/CN1) 0.357x (64.3% faster)
Base64 SIMD decode 694.000 ms
Base64 decode ratio (SIMD/native) 0.494x (50.6% faster)
Base64 decode ratio (SIMD/CN1) 0.491x (50.9% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 122.000 ms
Image createMask (SIMD on) 16.000 ms
Image createMask ratio (SIMD on/off) 0.131x (86.9% faster)
Image applyMask (SIMD off) 347.000 ms
Image applyMask (SIMD on) 164.000 ms
Image applyMask ratio (SIMD on/off) 0.473x (52.7% faster)
Image modifyAlpha (SIMD off) 123.000 ms
Image modifyAlpha (SIMD on) 107.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.870x (13.0% faster)
Image modifyAlpha removeColor (SIMD off) 373.000 ms
Image modifyAlpha removeColor (SIMD on) 170.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.456x (54.4% faster)
Image PNG encode (SIMD off) 1370.000 ms
Image PNG encode (SIMD on) 975.000 ms
Image PNG encode ratio (SIMD on/off) 0.712x (28.8% faster)
Image JPEG encode 875.000 ms

@shai-almog shai-almog merged commit 3f33dab into master Apr 25, 2026
14 of 15 checks passed
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.

stack overflow in edt

2 participants