| // Copyright (c) 2018 the R8 project authors. Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | package uninitializedfinal; | 
 |  | 
 | // Test that leaks an instance before its final field has been initialized to a thread that | 
 | // reads that field. This tests that redundant field load elimination does not eliminate | 
 | // field reads (even of final fields) that cross a monitor operation. | 
 | public class UninitializedFinalFieldLeak { | 
 |  | 
 |   public static class PollingThread extends Thread { | 
 |     public int result = 0; | 
 |     UninitializedFinalFieldLeak f; | 
 |  | 
 |     PollingThread(UninitializedFinalFieldLeak f) { | 
 |       this.f = f; | 
 |     } | 
 |  | 
 |     // Read the field a number of times. Then lock on the object to await field initialization. | 
 |     public void run() { | 
 |       result += f.i; | 
 |       result += f.i; | 
 |       result += f.i; | 
 |       f.threadReadsDone = true; | 
 |       synchronized (f) { | 
 |         result += f.i; | 
 |       } | 
 |       // The right result is 42. Reading the uninitialized 0 three times and then | 
 |       // reading the initialized value. It is safe to remove the two redundant loads | 
 |       // before the monitor operation. | 
 |       System.out.println(result); | 
 |     } | 
 |   } | 
 |  | 
 |   public final int i; | 
 |   public volatile boolean threadReadsDone = false; | 
 |  | 
 |   public UninitializedFinalFieldLeak() throws InterruptedException { | 
 |     // Leak the object to a thread and start the thread with the lock on the object taken. | 
 |     // Then allow the other thread to run and read the uninitialized field. | 
 |     // Finally, initialize the field and release the lock. | 
 |     PollingThread t = new PollingThread(this); | 
 |     synchronized (this) { | 
 |       t.start(); | 
 |       while (!threadReadsDone) { | 
 |         Thread.yield(); | 
 |       } | 
 |       i = 42; | 
 |     } | 
 |     t.join(); | 
 |   } | 
 |  | 
 |   public static void main(String[] args) throws InterruptedException { | 
 |     new UninitializedFinalFieldLeak(); | 
 |   } | 
 | } |