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