Bump bundled JCEF/CEF to 146.0.10 to fix macOS BrowserComponent crash (supersedes Fontations flag workaround) - #5525
Conversation
Chromium 135 (CEF 135 / JCEF 135.0.20) bundled with the JavaSE simulator ships the Skia "Fontations" Rust font backend. On recent macOS it panics in its color-table code path (has_any_color_table -> crash_in_rust_with_overflow) while laying out fonts, killing the simulator JVM with SIGTRAP (exit 133) as soon as a BrowserComponent paints. Pass --disable-features=FontationsFontBackend to CEF so Chromium falls back to the FreeType backend. The switch is added to the jcef args in CEFBrowserComponent.createArgs() (jcefmaven makes onBeforeCommandLineProcessing final, so args must be supplied to the builder). Chromium propagates --disable-features to the CEF helper subprocesses automatically via its FeatureList mechanism. - Gated to macOS so Windows/Linux behavior is unchanged. - Overridable via the -Dcef.disableFeatures system property (used verbatim when set, on any platform). - Simulator-only; the iOS (WKWebView) and Android (system WebView) ports are untouched. - Logs the final CEF arg list at startup for verification. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xWRvY1jXzi3522dBqFraD
There was a problem hiding this comment.
Pull request overview
This PR addresses a macOS-only JavaSE simulator crash in the embedded CEF-based BrowserComponent by disabling Chromium’s Fontations font backend via --disable-features=FontationsFontBackend, with an override mechanism for advanced users.
Changes:
- Adds a macOS default for Chromium
--disable-featuresto disableFontationsFontBackend. - Introduces
-Dcef.disableFeatures=...to override the--disable-featuresvalue (or disable the default). - Emits the final computed CEF argument list at startup.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * System property that overrides the value passed to Chromium's | ||
| * {@code --disable-features} switch. When set (even to the empty string) it is | ||
| * used verbatim; when unset the platform default from {@link #defaultDisableFeatures()} | ||
| * is applied. |
| args.add("--disable-features=" + disableFeatures); | ||
| } | ||
|
|
||
| System.out.println("CEF Args: " + args); |
…ntics - Log the final CEF arg list via com.codename1.io.Log (Log.DEBUG) instead of System.out, matching the rest of the CEF integration (JavaCEFSEPort) so it respects the log level/redirection rather than always writing to stdout. - Correct the cef.disableFeatures Javadoc to match the implementation: a non-empty value is used verbatim, and an empty value clears the default so no --disable-features switch is passed (the switch was never emitted for an empty value). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xWRvY1jXzi3522dBqFraD
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 12 screenshots: 12 matched. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Ports/JavaSE/src/com/codename1/impl/javase/cef/CEFBrowserComponent.java:126
DISABLE_FEATURES_PROPERTYis only used inside this class, so it can beprivateto avoid expanding the package API surface unnecessarily.
static final String DISABLE_FEATURES_PROPERTY = "cef.disableFeatures";
Ports/JavaSE/src/com/codename1/impl/javase/cef/CEFBrowserComponent.java:184
- The log message is built eagerly (
"CEF Args: " + args), even when DEBUG logging is disabled. Guarding it avoids the extratoString()/allocation work whenLog.getLevel()is higher than DEBUG.
Log.p("CEF Args: " + args, Log.DEBUG);
The JavaSE simulator renders BrowserComponent via me.friwi:jcefmaven, pinned to CEF/Chromium 135. Chromium 135's Skia "Fontations" Rust font backend panics on macOS (fontations_ffi ... has_any_color_table -> crash_in_rust_with_overflow, SIGTRAP / exit 133) as soon as a BrowserComponent paints. --disable-features=FontationsFontBackend (added earlier on this branch, see PR #5525) does not reliably stop this particular crash -- it governs the renderer web-font path, not the color-font path that panics, and is known upstream not to fully take effect. The real fix is upstream in a newer Chromium ("disable Fontations FontConfig indexing and disregard corrupted font caches"), so this bumps the bundled CEF instead of relying on the flag. jcefmaven 135.0.20 (CEF 135 / Chromium 135.0.7049.85) -> jcefmaven 146.0.10 (CEF 146 / Chromium 146.0.7680.179) - maven/pom.xml: update jcefmaven.version and jcef.version. The jcef.version is the exact me.friwi:jcef-api build tag jcefmaven 146.0.10 depends on transitively (jcef-d3de827+cef-146.0.10+g8219561+chromium-146.0.7680.179); scripts/ci-install-upstream-jcef-jar.sh downloads jcef-api by this string for the Ant build. Both artifacts confirmed resolvable from Maven Central. - CEFBrowserComponent: keep the macOS-gated FontationsFontBackend switch as a low-risk safety net (still overridable via -Dcef.disableFeatures) and note in the Javadoc that the crash is fixed upstream in the newer CEF. scripts/ci-install-upstream-jcef-jar.sh, maven/javase/pom.xml and CN1JcefRuntimeTest.java read the version from maven/pom.xml / the property and hardcode no version, so they need no change. On-device confirmation of paint-without-crash on macOS 15.4+ Apple Silicon is still required (no macOS host in CI). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xWRvY1jXzi3522dBqFraD
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Ports/JavaSE/src/com/codename1/impl/javase/cef/CEFBrowserComponent.java:188
- This adds a new debug log line printing the full CEF argument list. Since the PR description states behavior is unchanged in this file, either document this behavioral change (log output) in the PR description or gate it behind an explicit debug/system property so it doesn’t change default simulator logging.
Log.p("CEF Args: " + args, Log.DEBUG);
Ports/JavaSE/src/com/codename1/impl/javase/cef/CEFBrowserComponent.java:186
- The PR description says this file’s changes are Javadoc-only / “behavior unchanged”, but createArgs() now conditionally adds a new Chromium flag (--disable-features=...) based on the cef.disableFeatures system property and a macOS default. If this behavior change is intended as the retained safety net, please update the PR description accordingly; otherwise revert/guard this block to keep runtime args unchanged.
This issue also appears on line 188 of the same file.
String prop = System.getProperty(DISABLE_FEATURES_PROPERTY);
String disableFeatures = prop != null ? prop : defaultDisableFeatures();
if (disableFeatures != null && disableFeatures.length() > 0) {
args.add("--disable-features=" + disableFeatures);
}
|
Compared 151 screenshots: 151 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
After bumping to jcefmaven 146.0.10, the CEF+ffmpeg smoke test (and a real BrowserComponent app on macOS) failed at native-bundle extraction with: java.lang.IllegalAccessError: class ...compress.compressors.gzip .GzipCompressorInputStream tried to access protected method ...commons.io.build.AbstractStreamBuilder.getInputStream() at me.friwi.jcefmaven.impl.step.extract.TarGzExtractor.extractTarGZ JCEF Maven 146 pulls commons-compress 1.28.0, which calls AbstractStreamBuilder.getInputStream() and declares commons-io 2.20.0. The javase module pinned commons-io to 2.16.1 (sized for the old commons-compress 1.27.1 under jcefmaven 135), so the mismatch broke extraction. Note the crash happened AFTER CEF 146 downloaded and began extracting -- i.e. past the Fontations SIGTRAP the version bump set out to fix. - maven/javase/pom.xml: pin commons-io 2.16.1 -> 2.20.0 to match commons-compress 1.28.0's requirement. - scripts/ci-install-upstream-jcef-jar.sh: bump the Ant build's helper jars to the versions jcefmaven 146 resolves (commons-compress 1.28.0, commons-io 2.20.0, commons-codec 1.19.0, commons-lang3 3.18.0) so the Ant JavaSE build extracts the native bundle with the same, compatible stack. All four artifacts confirmed resolvable from Maven Central. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xWRvY1jXzi3522dBqFraD
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (4)
maven/javase/pom.xml:157
- PR description states no change is needed in maven/javase/pom.xml, but this PR does change it (pins commons-io to 2.20.0 and updates the explanatory comment). Please update the PR description (or revert this change if it’s not intended) so reviewers/CI triage have an accurate inventory of touched files.
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.20.0</version>
</dependency>
scripts/ci-install-upstream-jcef-jar.sh:63
- PR description says no change is needed in scripts/ci-install-upstream-jcef-jar.sh, but this PR updates the helper jar versions (commons-compress/codec/io/lang3) and adds new rationale comments. Please update the PR description (or revert the script changes if they’re not intended) so it accurately lists all modified files and behavioral impacts on the legacy Ant build.
install_artifact me/friwi jcef-api "$jcef_ver" jcef.jar
install_artifact me/friwi jcefmaven "$jcefmaven_ver" jcefmaven.jar
# These helper jars mirror JCEF Maven's transitive dependencies for the Ant
# build. Keep them aligned with the versions jcefmaven.version actually resolves
# (JCEF Maven 146 -> commons-compress 1.28.0, which in turn requires commons-io
# 2.20.0; a stale commons-io throws IllegalAccessError while extracting the
# native bundle). commons-codec/commons-lang3 track commons-compress 1.28.0.
install_artifact org/apache/commons commons-compress 1.28.0 commons-compress.jar
install_artifact com/google/code/gson gson 2.11.0 gson.jar
install_artifact commons-codec commons-codec 1.19.0 commons-codec.jar
install_artifact commons-io commons-io 2.20.0 commons-io.jar
install_artifact org/apache/commons commons-lang3 3.18.0 commons-lang3.jar
Ports/JavaSE/src/com/codename1/impl/javase/cef/CEFBrowserComponent.java:189
- PR description says the CEFBrowserComponent change is Javadoc-only and that behavior is unchanged, but this patch adds runtime behavior: it conditionally appends a new Chromium arg (--disable-features=...) based on a system property/default and also logs the full CEF args list. Please update the PR description (or adjust the code) so the documented scope matches the actual behavior changes.
String prop = System.getProperty(DISABLE_FEATURES_PROPERTY);
String disableFeatures = prop != null ? prop : defaultDisableFeatures();
if (disableFeatures != null && disableFeatures.length() > 0) {
args.add("--disable-features=" + disableFeatures);
}
Log.p("CEF Args: " + args, Log.DEBUG);
return args.toArray(new String[args.size()]);
maven/javase/pom.xml:151
- The comment says the reactor manages Commons IO at 2.14.0, but the root maven/pom.xml dependencyManagement currently pins commons-io to 2.16.1. This comment should be updated so it stays accurate for future bumps/debugging.
otherwise manages Commons IO at 2.14.0, so pin it here. Keep this in
The previous commit pinned commons-io 2.20.0 in maven/javase/pom.xml, but the root reactor's dependencyManagement still forced commons-io 2.16.1. Any reactor module that pulls codenameone-javase transitively -- notably the javase-cef-ffmpeg-smoke app used by the CI smoke test -- has commons-io managed back down to 2.16.1, so it kept hitting the IllegalAccessError from commons-compress 1.28.0 during JCEF native extraction even after the javase pin. dependencyManagement overrides transitive versions regardless of a downstream module's direct pin, so the managed version must move too. Bump the reactor management to 2.20.0 to match commons-compress 1.28.0 (and the javase pin). commons-codec/commons-lang3/commons-compress are not reactor-managed, so they already resolve to the versions JCEF Maven 146 needs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xWRvY1jXzi3522dBqFraD
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (3)
maven/javase/pom.xml:151
- The comment claims the reactor otherwise manages Commons IO at 2.14.0, but there is no such version pin elsewhere in this reactor (and the root pom now manages commons-io to 2.20.0). This makes the rationale misleading and likely to go stale again; please reword to avoid a specific outdated version number.
otherwise manages Commons IO at 2.14.0, so pin it here. Keep this in
scripts/ci-install-upstream-jcef-jar.sh:58
- The PR description says no change was needed in scripts/ci-install-upstream-jcef-jar.sh and that it hardcodes no version strings, but this change updates hardcoded helper-jar versions (commons-compress/codecs/io/lang3). Please update the PR description (or its "Files touched"/"No change needed" sections) to reflect this so maintainers know these pins must stay aligned with jcefmaven.version.
# These helper jars mirror JCEF Maven's transitive dependencies for the Ant
# build. Keep them aligned with the versions jcefmaven.version actually resolves
# (JCEF Maven 146 -> commons-compress 1.28.0, which in turn requires commons-io
# 2.20.0; a stale commons-io throws IllegalAccessError while extracting the
# native bundle). commons-codec/commons-lang3 track commons-compress 1.28.0.
Ports/JavaSE/src/com/codename1/impl/javase/cef/CEFBrowserComponent.java:186
- The PR description states CEFBrowserComponent behavior is unchanged, but createArgs() now conditionally adds a new Chromium argument (--disable-features=...) by default on macOS (unless -Dcef.disableFeatures overrides it). Please update the PR description to reflect this behavioral change so it’s clear the safety-net flag is being applied by default.
String prop = System.getProperty(DISABLE_FEATURES_PROPERTY);
String disableFeatures = prop != null ? prop : defaultDisableFeatures();
if (disableFeatures != null && disableFeatures.length() > 0) {
args.add("--disable-features=" + disableFeatures);
}
|
Compared 181 screenshots: 181 matched. |
The comment claimed the reactor manages commons-io at 2.14.0, but the root reactor dependencyManagement now pins it to 2.20.0 (matching this direct pin). Reword to describe why the direct pin remains -- it keeps standalone consumers of codenameone-javase, which don't inherit the reactor's dependencyManagement, on commons-io 2.20.0 as well. Addresses Copilot review feedback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017xWRvY1jXzi3522dBqFraD
|
Compared 217 screenshots: 217 matched. |
|
Compared 144 screenshots: 144 matched. |
|
Compared 149 screenshots: 149 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 143 screenshots: 143 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 148 screenshots: 148 matched. Benchmark Results
Detailed Performance Metrics
|
Problem
On macOS 15.4.x (Apple Silicon), the JavaSE simulator's embedded
BrowserComponentcrashes the JVM with exit code 133 (SIGTRAP) as soon as it paints. The crash is entirely inside the bundled Chromium Embedded Framework (JCEF 135.0.20 / CEF 135 / Chromium 135) on theCrBrowserMainthread:Chromium 135's Skia Fontations (Rust) font backend panics in its color-table code path while laying out fonts. This is simulator-only — iOS (WKWebView) and Android (system WebView) are unaffected — but it makes the simulator unusable for any app showing a
BrowserComponenton recent macOS.Fix: bump the bundled CEF/Chromium
The real fix is upstream in Chromium ("disable Fontations FontConfig indexing and disregard corrupted font caches"), so this PR moves the bundled CEF forward rather than relying on a Chromium switch:
135.0.20146.0.10This supersedes the earlier flag-only workaround on this branch.
--disable-features=FontationsFontBackenddoes not reliably stop this particular crash — it governs the renderer web-font path, not the color-font path that panics, and is known upstream not to fully take effect. The switch is kept as a low-risk, macOS-gated safety net (still overridable via-Dcef.disableFeatures); it is harmless on the newer CEF.Transitive-dependency fallout of the bump
JCEF Maven 146 pulls commons-compress 1.28.0, whose
GzipCompressorInputStreamcallsAbstractStreamBuilder.getInputStream()and therefore requires commons-io 2.20.0. With an older commons-io on the classpath, native-bundle extraction throwsIllegalAccessErrorat startup (theBrowserComponentnever paints). The repo previously pinned commons-io 2.16.1, so the bump had to carry a matching commons-io update through every path that assembles the simulator classpath (Maven reactor, thejavasemodule's own POM for standalone consumers, and the legacy Ant helper-jar script).Files touched
maven/pom.xmljcefmaven.version→146.0.10, andjcef.version→jcef-d3de827+cef-146.0.10+g8219561+chromium-146.0.7680.179. Thatjcef.versionstring is the exactme.friwi:jcef-apibuild tag that jcefmaven 146.0.10 depends on transitively (verified against jcefmaven's pom);scripts/ci-install-upstream-jcef-jar.shdownloadsjcef-apiby this string for the legacy Ant build.dependencyManagementbump of commons-io 2.16.1 → 2.20.0. BecausedependencyManagementoverrides transitive versions regardless of a downstream module's direct pin, this is what actually fixes the CI CEF/FFmpeg smoke app (a reactor module that pullscodenameone-javasetransitively).maven/javase/pom.xml— pins commons-io 2.20.0 directly (with an updated rationale comment). This keeps standalone consumers ofcodenameone-javase— which don't inherit the reactor'sdependencyManagement— on 2.20.0 as well.scripts/ci-install-upstream-jcef-jar.sh— aligns the helper jars installed for the legacy Ant build (commons-compress 1.28.0,commons-codec 1.19.0,commons-io 2.20.0,commons-lang3 3.18.0) with what jcefmaven 146 resolves, plus a comment explaining they must trackjcefmaven.version.Ports/JavaSE/src/com/codename1/impl/javase/cef/CEFBrowserComponent.javaFontationsFontBackendswitch is retained only as a safety net.createArgs()appends--disable-features=FontationsFontBackendby default;-Dcef.disableFeatures=<value>overrides it (empty value disables the default). The final computed CEF argument list is logged via the Codename OneLogfacility atDEBUG.Verification
me.friwi:jcefmaven:146.0.10andme.friwi:jcef-api:jcef-d3de827+cef-146.0.10+g8219561+chromium-146.0.7680.179.jcef-apidependency at exactly thejcef.versionstring above.build-test/ static-analysis legs are green on the tip; the CEF/FFmpeg smoke matrix (ubuntu/windows/macos) exercises the extraction path that the commons-io fix targets.BrowserComponentpaint.🤖 Generated with Claude Code