1 import sun.misc.Unsafe; 2 3 import java.lang.reflect.Field; 4 5 public class Main { 6 private static Unsafe UNSAFE; 7 main(String[] args)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 */ setUp()43 public static void setUp() { 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 try { 50 Field field = Unsafe.class.getDeclaredField("THE_ONE"); 51 field.setAccessible(true); 52 53 UNSAFE = (Unsafe) field.get(null); 54 } catch (NoSuchFieldException ex) { 55 throw new RuntimeException(ex); 56 } catch (IllegalAccessException ex) { 57 throw new RuntimeException(ex); 58 } 59 } 60 61 /** 62 * Scribbles on the stack to help ensure we don't have a fake 63 * pointer that would keep would-be garbage alive. 64 */ clearStack(int depth)65 private static void clearStack(int depth) { 66 int a = 0; 67 int b = 0; 68 int c = 0; 69 int d = 0; 70 int e = 0; 71 int f = 0; 72 int g = 0; 73 int h = 0; 74 int i = 0; 75 int j = 0; 76 77 if (depth > 0) { 78 clearStack(depth - 1); 79 } 80 } 81 82 private static class ParkTester extends Thread { 83 public volatile boolean parkNow = false; 84 public volatile boolean success = false; 85 run()86 public void run() { 87 while (!parkNow) { 88 try { 89 Thread.sleep(500); 90 } catch (InterruptedException ex) { 91 // Ignore it. 92 } 93 } 94 95 long start = System.currentTimeMillis(); 96 UNSAFE.park(false, 500 * 1000000); // 500 msec 97 long elapsed = System.currentTimeMillis() - start; 98 99 if (elapsed > 200) { 100 System.out.println("park()ed for " + elapsed + " msec"); 101 success = false; 102 } else { 103 System.out.println("park() returned quickly"); 104 success = true; 105 } 106 } 107 } 108 } 109