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.gc(); 22 23 System.out.println("Asking thread to park"); 24 test.parkNow = true; 25 26 try { 27 Thread.sleep(1500); 28 } catch (InterruptedException ex) { 29 // Ignore it. 30 } 31 32 if (test.success) { 33 System.out.println("Test succeeded!"); 34 } else { 35 System.out.println("Test failed."); 36 } 37 } 38 39 /** 40 * Set up {@link #UNSAFE}. 41 */ setUp()42 public static void setUp() { 43 /* 44 * Subvert the access check to get the unique Unsafe instance. 45 * We can do this because there's no security manager 46 * installed when running the test. 47 */ 48 try { 49 Field field = Unsafe.class.getDeclaredField("THE_ONE"); 50 field.setAccessible(true); 51 52 UNSAFE = (Unsafe) field.get(null); 53 } catch (NoSuchFieldException ex) { 54 throw new RuntimeException(ex); 55 } catch (IllegalAccessException ex) { 56 throw new RuntimeException(ex); 57 } 58 } 59 60 /** 61 * Scribbles on the stack to help ensure we don't have a fake 62 * pointer that would keep would-be garbage alive. 63 */ clearStack(int depth)64 private static void clearStack(int depth) { 65 int a = 0; 66 int b = 0; 67 int c = 0; 68 int d = 0; 69 int e = 0; 70 int f = 0; 71 int g = 0; 72 int h = 0; 73 int i = 0; 74 int j = 0; 75 76 if (depth > 0) { 77 clearStack(depth - 1); 78 } 79 } 80 81 private static class ParkTester extends Thread { 82 public volatile boolean parkNow = false; 83 public volatile boolean success = false; 84 run()85 public void run() { 86 while (!parkNow) { 87 try { 88 Thread.sleep(500); 89 } catch (InterruptedException ex) { 90 // Ignore it. 91 } 92 } 93 94 long start = System.currentTimeMillis(); 95 UNSAFE.park(false, 500 * 1000000); // 500 msec 96 long elapsed = System.currentTimeMillis() - start; 97 98 if (elapsed > 200) { 99 System.out.println("park()ed for " + elapsed + " msec"); 100 success = false; 101 } else { 102 System.out.println("park() returned quickly"); 103 success = true; 104 } 105 } 106 } 107 } 108