Søren Gjesse | 1848f40 | 2018-07-11 12:57:01 +0200 | [diff] [blame] | 1 | // 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 | |
| 5 | package 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. |
| 10 | public 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 | } |