1# Java Asserts in Chromium 2This doc exists to explain how asserts in Java are enabled and disabled by 3Chromium's build system. 4 5## javac Assertion Bytecode 6Whenever javac compiles a Java class, assertions are transformed into the 7following bytecode: 8 9``` 10 Code: 11 0: getstatic #2 // Static field $assertionsDisabled 12 3: ifne 20 // Conditional jump past assertion throw 13 12: new #3 // Class java/lang/AssertionError 14 19: athrow // Throwing AssertionError 15 20: return 16 17// NOTE: this static block was made just to check the desiredAssertionStatus. 18// There was no static block on the class before javac created one. 19 static {}; 20 Code: 21 2: invokevirtual #6 // Method java/lang/Class.desiredAssertionStatus() 22 5: ifne 12 23 8: iconst_1 24 9: goto 13 25 12: iconst_0 26 13: putstatic #2 // Static field $assertionsDisabled 27 16: return 28``` 29 30TL;DR - every single assertion is gated behind a `assertionDisabled` flag check, 31which is a static field that can be set by the JRE's 32`setDefaultAssertionStatus`, `setPackageAssertionStatus`, and 33`setClassAssertionStatus` methods. 34 35## Assertion Enabling/Disabling 36Our tools which consume javac output, namely R8 and D8, each have flags which 37the build system uses to enable or disable asserts. We control this with the 38`enable_java_asserts` gn arg. It does this by deleting the gating check on 39`assertionsDisabled` when enabling, and by eliminating any reference to the 40assert when disabling. 41 42```java 43// Example equivalents of: 44a = foo(); 45assert a != 0; 46return a; 47 48// Traditional, unoptimized javac output. 49a = foo(); 50if (!assertionsDisabled && a == 0) { 51 throw new AssertionError(); 52} 53return a; 54 55// Optimized with assertions enabled. 56a = foo(); 57if (a == 0) { 58 throw new AssertionError(); 59} 60return a; 61 62// Optimized with assertions disabled. 63a = foo(); 64return a; 65``` 66 67## Assertion Enabling on Canary 68Recently we [enabled 69asserts](https://chromium-review.googlesource.com/c/chromium/src/+/3307087) on 70Canary. It spiked our crash rate, and it was decided to not do this again, as 71it's bad user experience to crash the app incessantly for non-fatal issues. 72 73So, we asked the R8 team for a feature which would rewrite the bytecode of these 74assertions, which they implemented for us. Now, instead of just turning it on 75and throwing an `AssertionError`, [R8 would call a provided assertion 76handler](https://r8.googlesource.com/r8/+/aefe7bc18a7ce19f3e9c6dac0bedf6d182bbe142/src/main/java/com/android/tools/r8/ParseFlagInfoImpl.java#124) 77with the `AssertionError`. We then wrote a [silent assertion 78reporter](https://chromium-review.googlesource.com/c/chromium/src/+/3746261) 79and this reports Java `AssertionErrors` to our crash server without crashing 80the browser. 81