File: java.md

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (502 lines) | stat: -rw-r--r-- 17,785 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
# Chromium Java Style Guide

_For other languages, please see the [Chromium style
guides](https://chromium.googlesource.com/chromium/src/+/main/styleguide/styleguide.md)._

Chromium follows the [Android Open Source style
guide](http://source.android.com/source/code-style.html) unless an exception
is listed below.

You can propose changes to this style guide by sending an email to
`java@chromium.org`. Ideally, the list will arrive at some consensus and you can
request review for a change to this file. If there's no consensus,
[`//styleguide/java/OWNERS`](https://chromium.googlesource.com/chromium/src/+/main/styleguide/java/OWNERS)
get to decide.

[TOC]

## Java Language Features

### Type Deduction using "var" {#var}

A variable declaration can use the `var` keyword in place of the type (similar
to the `auto` keyword in C++). In line with the [guidance for
C++](https://google.github.io/styleguide/cppguide.html#Type_deduction), the
`var` keyword may be used when it aids readability and the type of the value is
already clear (ex. `var bundle = new Bundle()` is OK, but `var something =
returnValueIsNotObvious()` may be unclear to readers who are new to this part of
the code).

The `var` keyword may also be used in try-with-resources when the resource is
not directly accessed (or when it falls under the previous guidance), such as:

```java
try (var ignored = StrictModeContext.allowDiskWrites()) {
    // 'var' is permitted so long as the 'ignored' variable is not used directly
    // in the code.
}
```

### Exceptions

A quick primer:

* `Throwable`: Base class for all exceptions
  * `Error`: Base class for exceptions which are meant to crash the app.
  * `Exception`: Base class for exceptions that make sense the `catch`.
    * `RuntimeException`: Base class for exceptions that do not need to be
       declared as `throws` ("unchecked exceptions").

#### Broad Catch Handlers {#broad-catches}

Use catch statements that do not catch exceptions they are not meant to.
 * There is rarely a valid reason to `catch (Throwable t)`, since that
   includes the (generally unrecoverable) `Error` types.

Use `catch (Exception e)` when working with OS APIs that might throw
(assuming the program can recover from them).
 * There have been many cases of crashes caused by `IllegalStateException` /
   `IllegalArgumentException` / `SecurityException` being thrown where only
   `RemoteException` was being caught. Unless catch handlers will differ
   based on exception type, just catch `Exception`.

Do not use `catch (RuntimeException e)`.
 * It is useful to extend `RuntimeException` to make unchecked exception
   types, but the type does not make much sense in `catch` clauses, as
   there are not times when you'd want to catch all unchecked exceptions,
   but not also want to catch all checked exceptions.

#### Exception Messages {#exception-messages}

Avoid adding messages to exceptions that do not aid in debugging. For example:

```java
try {
    somethingThatThrowsIOException();
} catch (IOException e) {
    // Bad - message does not tell you more than the stack trace does:
    throw new RuntimeException("Failed to parse a file.", e);
    // Good - conveys that this block failed along with the "caused by" exception.
    throw new RuntimeException(e);
    // Good - adds useful information.
    throw new RuntimeException(String.format("Failed to parse %s", fileName), e);
}
```

#### Wrapping with RuntimeException {#throw-unchecked}

It is common to wrap a checked exception with a RuntimeException for cases
where a checked exception is not recoverable, or not possible. In order to
reduce the number of stack trace "caused by" clauses, and to save on binary
size, use [`JavaUtils.throwUnchecked()`] instead.

```java
try {
    somethingThatThrowsIOException();
} catch (IOException e) {
    // Bad - RuntimeException adds no context and creates longer stack traces.
    throw new RuntimeException(e);
    // Good - Original exception is preserved.
    throw JavaUtils.throwUnchecked(e);
}
```

*** note
Do not use `throwUnchecked()` when the exception may want to be caught.
***


[`JavaUtils.throwUnchecked()`]: https://source.chromium.org/search?q=symbol:JavaUtils.throwUnchecked

### Asserts

The build system:
 * strips asserts in release builds (via R8),
 * enables them in debug builds,
 * and enables them in report-only mode for Canary builds.

```java
// Code for assert expressions & messages is removed when asserts are disabled.
assert someCallWithoutSideEffects(param) : "Call failed with: " + param;
```

Use your judgement for when to use asserts vs exceptions. Generally speaking,
use asserts to check program invariants (e.g. parameter constraints) and
exceptions for unrecoverable error conditions (e.g. OS errors). You should tend
to use exceptions more in privacy / security-sensitive code.

Do not add checks when the code will crash anyways. E.g.:

```java
// Don't do this.
assert(foo != null);
foo.method(); // This will throw anyways.
```

For multi-statement asserts, use [`BuildConfig.ENABLE_ASSERTS`] to guard your
code (similar to `#if DCHECK_IS_ON()` in C++). E.g.:

```java
import org.chromium.build.BuildConfig;

...

if (BuildConfig.ENABLE_ASSERTS) {
    // Any code here will be stripped in release builds by R8.
    ...
}
```

[`BuildConfig.ENABLE_ASSERTS`]: https://source.chromium.org/search?q=symbol:BuildConfig%5C.ENABLE_ASSERTS

#### DCHECKS vs Java Asserts  {#asserts}

`DCHECK` and `assert` are similar, but our guidance for them differs:
 * CHECKs are preferred in C++, whereas asserts are preferred in Java.

This is because as a memory-safe language, logic bugs in Java are much less
likely to be exploitable.

### toString()  {#toString}

Use explicit serialization methods (e.g. `toDebugString()` or `getDescription()`)
instead of `toString()` when dynamic dispatch is not required.

1. R8 cannot detect when `toString()` is unused, so overrides will not be stripped
   when unused.
2. R8 cannot optimize / inline these calls as well as non-overriding methods.

### Records & AutoValue {#records}

```java
// Banned.
record Rectangle(float length, float width) {}
```

**Rationale:**
 * To avoid dead code:
   * Records and `@AutoValue` generate `equals()`, `hashCode()`, and `toString()`,
     which `R8` is unable to remove when unused.
   * When these methods are required, implement them explicitly so that the
     intention is clear.
 * Also - supporting `record` requires build system work ([crbug/1493366]).

Example with `equals()` and `hashCode()`:

```java
public class ValueClass {
    private final SomeClass mObjMember;
    private final int mIntMember;

    @Override
    public boolean equals(Object o) {
        return o instanceof ValueClass vc
                && Objects.equals(mObjMember, vc.mObjMember)
                && mIntMember == vc.mIntMember;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mObjMember, mIntMember);
    }
}
```

[crbug/1493366]: https://crbug.com/1493366

### Enums

Banned. Use [`@IntDef`](#intdefs) instead.

**Rationale:**

Java enums generate a lot of bytecode. Use constants where possible. When a
custom type hierarchy is required, use explicit classes with inheritance.

### Finalizers

In line with [Google's Java style guide] and [Android's Java style guide],
never override `Object.finalize()`.

Custom finalizers:
* are called on a background thread, and at an unpredicatble point in time,
* swallow all exceptions (asserts won't work),
* causes additional garbage collector jank.

Classes that need destructor logic should provide an explicit `destroy()`
method. Use [LifetimeAssert](https://chromium.googlesource.com/chromium/src/+/main/base/android/java/src/org/chromium/base/lifetime/LifetimeAssert.java)
to ensure in debug builds and tests that `destroy()` is called.

[Google's Java style guide]: https://google.github.io/styleguide/javaguide.html#s6.4-finalizers
[Android's Java style guide]: https://source.android.com/docs/setup/contribute/code-style#dont-use-finalizers

## Nullability Annotations

A migration to add `@NullMarked` to all Java files is currently underway
([crbug.com/389129271]). See [nullaway.md] for how to use `@Nullable` and
related annotations.

[crbug.com/389129271]: https://crbug.com/389129271
[nullaway.md]: nullaway.md

## Java Library APIs

Android provides the ability to bundle copies of `java.*` APIs alongside
application code, known as [Java Library Desugaring]. However, since this
bundling comes with a performance cost, Chrome does not use it. Treat `java.*`
APIs the same as you would `android.*` ones and guard them with
`Build.VERSION.SDK_INT` checks [when necessary]. The one exception is if the
method is [directly backported by D8] (these are okay to use, since they are
lightweight). Android Lint will fail if you try to use an API without a
corresponding `Build.VERSION.SDK_INT` guard or `@RequiresApi` annotation.

[Java Library Desugaring]: https://developer.android.com/studio/write/java8-support-table
[when necessary]: https://developer.android.com/reference/packages
[directly backported by D8]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/r8/backported_methods.txt

### Logging

* Use `org.chromium.base.Log` instead of `android.util.Log`.
  * It provides `%s` support, and ensures log stripping works correctly.
* Minimize the use of `Log.w()` and `Log.e()`.
  * Debug and Info log levels are stripped by ProGuard in release builds, and
    so have no performance impact for shipping builds. However, Warning and
    Error log levels are not stripped.
* Function calls in log parameters are *not* stripped by ProGuard.

```java
Log.d(TAG, "There are %d cats", countCats());  // countCats() not stripped.
```

### Streams

Using [Java streams] outside of tests is strongly discouraged. If you can write
your code as an explicit loop, then do so. The primary reason for this guidance
is because the lambdas and method references needed for streams almost always
result in larger binary size than their loop equivalents (see
[crbug.com/344943957] for examples).

The `parallel()` and `parallelStream()` APIs are simpler than their loop
equivalents, but are banned due to a lack of a compelling use case in Chrome.
If you find one, please discuss on `java@chromium.org`.

Use of `stream()` without a lambda / method reference is allowed. E.g.:

```java
@SuppressWarnings("NoStreams")
private static List<Integer> boxInts(int[] arr) {
    return Arrays.stream(arr).boxed().collect(Collectors.toList());
}

@SuppressWarnings("NoStreams")
private static List<String> readLines(BufferedReader bufferedReader) {
    return bufferedReader.lines().collect(Collectors.toList());
}
```

[Java streams]: https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
[crbug.com/344943957]: https://crbug.com/344943957

### AndroidX Annotations {#annotations}

* Use them liberally. They are [documented here](https://developer.android.com/studio/write/annotations).
  * They generally improve readability.
  * Many make lint more useful.
* What about `androidx.annotation.Nullable`?
  * We are migrating away from it (see [nullaway.md]).
  * Keep using it in files that have not yet been migrated.

#### IntDefs {#intdefs}

Values can be declared outside or inside the `@interface`. Chromium style is
to declare inside.

```java
@IntDef({ContactsPickerAction.CANCEL, ContactsPickerAction.CONTACTS_SELECTED,
        ContactsPickerAction.SELECT_ALL, ContactsPickerAction.UNDO_SELECT_ALL})
@Retention(RetentionPolicy.SOURCE)
public @interface ContactsPickerAction {
    int CANCEL = 0;
    int CONTACTS_SELECTED = 1;
    int SELECT_ALL = 2;
    int UNDO_SELECT_ALL = 3;
    int NUM_ENTRIES = 4;
}
// ...
void onContactsPickerUserAction(@ContactsPickerAction int action, ...);
```

Values of `Integer` type are also supported, which allows using a sentinel
`null` if needed.

[@IntDef annotation]: https://developer.android.com/studio/write/annotations#enum-annotations
[Android lint]: https://chromium.googlesource.com/chromium/src/+/HEAD/build/android/docs/lint.md


## Style / Formatting {#style}

### File Headers
* Use the same format as in the [C++ style guide](https://chromium.googlesource.com/chromium/src/+/main/styleguide/c++/c++.md#File-headers).

### TODOs

* TODO should follow chromium convention. Examples:
  * `TODO(username): Some sentence here.`
  * `TODO(crbug.com/40192027): Even better to use a bug for context.`

### Parameter Comments

Use [parameter comments] when they aid in the readability of a function call.

E.g.:

```java
someMethod(/* enabled= */ true, /* target= */ null, defaultValue);
```

[parameter comments]: https://errorprone.info/bugpattern/ParameterName

### Default Field Initializers

* Fields should not be explicitly initialized to default values (see
  [here](https://groups.google.com/a/chromium.org/d/topic/chromium-dev/ylbLOvLs0bs/discussion)).

### Curly Braces

Conditional braces should be used, but are optional if the conditional and the
statement can be on a single line.

Do:

```java
if (someConditional) return false;
for (int i = 0; i < 10; ++i) callThing(i);
```

or

```java
if (someConditional) {
    return false;
}
```

Do NOT do:

```java
if (someConditional)
    return false;
```

### Import Order

* Static imports go before other imports.
* Each import group must be separated by an empty line.

This is the order of the import groups:

1. android
1. androidx
1. com (except com.google.android.apps.chrome)
1. dalvik
1. junit
1. org
1. com.google.android.apps.chrome
1. org.chromium
1. java
1. javax

## Testing

Googlers, see [go/clank-test-strategy](http://go/clank-test-strategy).

In summary:

* Use real dependencies when feasible and fast. Use Mockito’s `@Mock` most
  of the time, but write fakes for frequently used dependencies.

* Do not use Robolectric Shadows for Chromium code.
  * Shadows make code harder to refactor.
  * Prefer to refactor code to make it more testable.
  * When you really need to use a test double for a static method, add a
    `setFooForTesting() [...]` method to make the test contract explicit.
    * Use [`ResettersForTesting.register()`] from within `ForTesting()`
      methods to ensure that state is reset between tests.

* Use Robolectric when possible (when tests do not require native). Other
  times, use on-device tests with one of the following annotations:
  * [`@Batch(UNIT_TESTS)`] for unit tests
  * [`@Batch(PER_CLASS)`] for integration tests
  * [`@DoNotBatch`] for when each test method requires an app restart

[`ResettersForTesting.register()`]: https://source.chromium.org/search?q=symbol:ResettersForTesting.register
[`@Batch(UNIT_TESTS)`]: https://source.chromium.org/search?q=symbol:Batch.UNIT_TESTS
[`@Batch(PER_CLASS)`]: https://source.chromium.org/search?q=symbol:Batch.PER_CLASS
[`@DoNotBatch`]: https://source.chromium.org/search?q=symbol:DoNotBatch

### Test-only Code

Functions and fields used only for testing should have `ForTesting` as a
suffix so that:

1. The `android-binary-size` trybot can [ensure they are removed] in
   non-test optimized builds (by R8).
2. [`PRESUMBIT.py`] can ensure no calls are made to such methods outside of
   tests, and

`ForTesting` methods that are `@CalledByNative` should use
`@CalledByNativeForTesting` instead.

Symbols that are made public (or package-private) for the sake of tests
should be annotated with [`@VisibleForTesting`]. Android Lint will check
that calls from non-test code respect the "otherwise" visibility.

Symbols with a `ForTesting` suffix **should not** be annotated with
`@VisibleForTesting`. While `otherwise=VisibleForTesting.NONE` exists, it
is redundant given the "ForTesting" suffix and the associated lint check
is redundant given our trybot check. You should, however, use it for
test-only constructors.

[ensure they are removed]: /docs/speed/binary_size/android_binary_size_trybot.md#Added-Symbols-named-ForTest
[`PRESUMBIT.py`]: https://chromium.googlesource.com/chromium/src/+/main/PRESUBMIT.py
[`@VisibleForTesting`]: https://developer.android.com/reference/androidx/annotation/VisibleForTesting

## Location

"Top level directories" are defined as directories with a GN file, such as
[//base](https://chromium.googlesource.com/chromium/src/+/main/base/)
and
[//content](https://chromium.googlesource.com/chromium/src/+/main/content/),
Chromium Java should live in a directory named
`<top level directory>/android/java`, with a package name
`org.chromium.<top level directory>`.  Each top level directory's Java should
build into a distinct JAR that honors the abstraction specified in a native
[checkdeps](https://chromium.googlesource.com/chromium/buildtools/+/main/checkdeps/checkdeps.py)
(e.g. `org.chromium.base` does not import `org.chromium.content`).  The full
path of any java file should contain the complete package name.

For example, top level directory `//base` might contain a file named
`base/android/java/org/chromium/base/Class.java`. This would get compiled into a
`chromium_base.jar` (final JAR name TBD).

`org.chromium.chrome.browser.foo.Class` would live in
`chrome/android/java/org/chromium/chrome/browser/foo/Class.java`.

New `<top level directory>/android` directories should have an `OWNERS` file
much like
[//base/android/OWNERS](https://chromium.googlesource.com/chromium/src/+/main/base/android/OWNERS).

## Tools

`google-java-format` is used to auto-format Java files. Formatting of its code
should be accepted in code reviews.

You can run `git cl format` to apply the automatic formatting.

Chromium also makes use of several [static analysis] tools.

[static analysis]: /build/android/docs/static_analysis.md

## Miscellany

* Use UTF-8 file encodings and LF line endings.