Home | History | Annotate | Download | only in src
      1 import sun.misc.Unsafe;
      2 
      3 import java.lang.reflect.Field;
      4 
      5 public class Main {
      6     private static Unsafe UNSAFE;
      7 
      8     public static void main(String[] args) throws Exception {
      9         setUp();
     10 
     11         ParkTester test = new ParkTester();
     12 
     13         System.out.println("Test starting");
     14 
     15         test.start();
     16         UNSAFE.unpark(test);
     17         clearStack(10);
     18 
     19         System.out.println("GC'ing");
     20         System.gc();
     21         System.runFinalization();
     22         System.gc();
     23 
     24         System.out.println("Asking thread to park");
     25         test.parkNow = true;
     26 
     27         try {
     28             Thread.sleep(1500);
     29         } catch (InterruptedException ex) {
     30             // Ignore it.
     31         }
     32 
     33         if (test.success) {
     34             System.out.println("Test succeeded!");
     35         } else {
     36             System.out.println("Test failed.");
     37         }
     38     }
     39 
     40     /**
     41      * Set up {@link #UNSAFE}.
     42      */
     43     public static void setUp() throws Exception{
     44         /*
     45          * Subvert the access check to get the unique Unsafe instance.
     46          * We can do this because there's no security manager
     47          * installed when running the test.
     48          */
     49         Field field = null;
     50         try {
     51             field = Unsafe.class.getDeclaredField("THE_ONE");
     52         } catch (NoSuchFieldException e1) {
     53             try {
     54                 field = Unsafe.class.getDeclaredField("theUnsafe");
     55             } catch (NoSuchFieldException e2) {
     56                 throw new RuntimeException("Failed to find THE_ONE or theUnsafe");
     57             }
     58         }
     59         field.setAccessible(true);
     60         UNSAFE = (Unsafe) field.get(null);
     61     }
     62 
     63     /**
     64      * Scribbles on the stack to help ensure we don't have a fake
     65      * pointer that would keep would-be garbage alive.
     66      */
     67     private static void clearStack(int depth) {
     68         int a = 0;
     69         int b = 0;
     70         int c = 0;
     71         int d = 0;
     72         int e = 0;
     73         int f = 0;
     74         int g = 0;
     75         int h = 0;
     76         int i = 0;
     77         int j = 0;
     78 
     79         if (depth > 0) {
     80             clearStack(depth - 1);
     81         }
     82     }
     83 
     84     private static class ParkTester extends Thread {
     85         public volatile boolean parkNow = false;
     86         public volatile boolean success = false;
     87 
     88         public void run() {
     89             while (!parkNow) {
     90                 try {
     91                     Thread.sleep(500);
     92                 } catch (InterruptedException ex) {
     93                     // Ignore it.
     94                 }
     95             }
     96 
     97             long start = System.currentTimeMillis();
     98             UNSAFE.park(false, 500 * 1000000); // 500 msec
     99             long elapsed = System.currentTimeMillis() - start;
    100 
    101             if (elapsed > 200) {
    102                 System.out.println("park()ed for " + elapsed + " msec");
    103                 success = false;
    104             } else {
    105                 System.out.println("park() returned quickly");
    106                 success = true;
    107             }
    108         }
    109     }
    110 }
    111