
Change-Id: Ibd45b235c9547dd83b27fedbd414fa5c5eb6a42a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3781549 Reviewed-by: Samuel Huang <huangs@chromium.org> Auto-Submit: Sam Maier <smaier@chromium.org> Commit-Queue: Samuel Huang <huangs@chromium.org> Cr-Commit-Position: refs/heads/main@{#1027416}
2.8 KiB
Java Asserts in Chromium
This doc exists to explain how asserts in Java are enabled and disabled by Chromium's build system.
javac Assertion Bytecode
Whenever javac compiles a Java class, assertions are transformed into the following bytecode:
Code:
0: getstatic #2 // Static field $assertionsDisabled
3: ifne 20 // Conditional jump past assertion throw
12: new #3 // Class java/lang/AssertionError
19: athrow // Throwing AssertionError
20: return
// NOTE: this static block was made just to check the desiredAssertionStatus.
// There was no static block on the class before javac created one.
static {};
Code:
2: invokevirtual #6 // Method java/lang/Class.desiredAssertionStatus()
5: ifne 12
8: iconst_1
9: goto 13
12: iconst_0
13: putstatic #2 // Static field $assertionsDisabled
16: return
TL;DR - every single assertion is gated behind a assertionDisabled
flag check,
which is a static field that can be set by the JRE's
setDefaultAssertionStatus
, setPackageAssertionStatus
, and
setClassAssertionStatus
methods.
Assertion Enabling/Disabling
Our tools which consume javac output, namely R8 and D8, each have flags which
the build system uses to enable or disable asserts. We control this with the
enable_java_asserts
gn arg. It does this by deleting the gating check on
assertionsDisabled
when enabling, and by eliminating any reference to the
assert when disabling.
// Example equivalents of:
a = foo();
assert a != 0;
return a;
// Traditional, unoptimized javac output.
a = foo();
if (!assertionsDisabled && a == 0) {
throw new AssertionError();
}
return a;
// Optimized with assertions enabled.
a = foo();
if (a == 0) {
throw new AssertionError();
}
return a;
// Optimized with assertions disabled.
a = foo();
return a;
Assertion Enabling on Canary
Recently we enabled asserts on Canary. It spiked our crash rate, and it was decided to not do this again, as it's bad user experience to crash the app incessantly for non-fatal issues.
So, we asked the R8 team for a feature which would rewrite the bytecode of these
assertions, which they implemented for us. Now, instead of just turning it on
and throwing an AssertionError
, R8 would call a provided assertion
handler
with the AssertionError
. We then wrote a silent assertion
reporter
and this reports Java AssertionErrors
to our crash server without crashing
the browser.