This doc exists to explain how asserts in Java are enabled and disabled by Chromium's build system.
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.
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;
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.