Skip to content

Commit

Permalink
Adding java_asserts.md doc
Browse files Browse the repository at this point in the history
Bug: 1185148
Change-Id: If2cc0c16b03b83498c090e577533377b9cd04811
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3778200
Reviewed-by: Samuel Huang <huangs@chromium.org>
Commit-Queue: Sam Maier <smaier@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1027330}
  • Loading branch information
Sam Maier authored and Chromium LUCI CQ committed Jul 22, 2022
1 parent fe7c98c commit 11ca8b4
Showing 1 changed file with 80 additions and 0 deletions.
80 changes: 80 additions & 0 deletions build/android/docs/java_asserts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# 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.

```java
// 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](https://chromium-review.googlesource.com/c/chromium/src/+/3307087) 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 with an ask to allow us to 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](https://r8.googlesource.com/r8/+/aefe7bc18a7ce19f3e9c6dac0bedf6d182bbe142/src/main/java/com/android/tools/r8/ParseFlagInfoImpl.java#124)
with the `AssertionError`. We then wrote a [silent assertion
reporter](https://chromium-review.googlesource.com/c/chromium/src/+/3746261)
and this reports Java `AssertionErrors` to our crash server without crashing
the browser.

0 comments on commit 11ca8b4

Please sign in to comment.