blob: 781d2b4975e0bfe09c15190207e0086036b325f9 [file] [log] [blame]
Søren Gjesse1848f402018-07-11 12:57:01 +02001// Copyright (c) 2018 the R8 project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5package uninitializedfinal;
6
7// Test that leaks an instance before its final field has been initialized to a thread that
8// reads that field. This tests that redundant field load elimination does not eliminate
9// field reads (even of final fields) that cross a monitor operation.
10public class UninitializedFinalFieldLeak {
11
12 public static class PollingThread extends Thread {
13 public int result = 0;
14 UninitializedFinalFieldLeak f;
15
16 PollingThread(UninitializedFinalFieldLeak f) {
17 this.f = f;
18 }
19
20 // Read the field a number of times. Then lock on the object to await field initialization.
21 public void run() {
22 result += f.i;
23 result += f.i;
24 result += f.i;
25 f.threadReadsDone = true;
26 synchronized (f) {
27 result += f.i;
28 }
29 // The right result is 42. Reading the uninitialized 0 three times and then
30 // reading the initialized value. It is safe to remove the two redundant loads
31 // before the monitor operation.
32 System.out.println(result);
33 }
34 }
35
36 public final int i;
37 public volatile boolean threadReadsDone = false;
38
39 public UninitializedFinalFieldLeak() throws InterruptedException {
40 // Leak the object to a thread and start the thread with the lock on the object taken.
41 // Then allow the other thread to run and read the uninitialized field.
42 // Finally, initialize the field and release the lock.
43 PollingThread t = new PollingThread(this);
44 synchronized (this) {
45 t.start();
46 while (!threadReadsDone) {
47 Thread.yield();
48 }
49 i = 42;
50 }
51 t.join();
52 }
53
54 public static void main(String[] args) throws InterruptedException {
55 new UninitializedFinalFieldLeak();
56 }
57}