xref: /aosp_15_r20/external/angle/build/android/docs/java_asserts.md (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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