import sun.misc.Unsafe; import java.lang.reflect.Field; public class Main { private static Unsafe UNSAFE; public static void main(String[] args) throws Exception { setUp(); ParkTester test = new ParkTester(); System.out.println("Test starting"); test.start(); UNSAFE.unpark(test); clearStack(10); System.out.println("GC'ing"); System.gc(); System.runFinalization(); System.gc(); System.out.println("Asking thread to park"); test.parkNow = true; try { Thread.sleep(1500); } catch (InterruptedException ex) { // Ignore it. } if (test.success) { System.out.println("Test succeeded!"); } else { System.out.println("Test failed."); } } /** * Set up {@link #UNSAFE}. */ public static void setUp() { /* * Subvert the access check to get the unique Unsafe instance. * We can do this because there's no security manager * installed when running the test. */ try { Field field = Unsafe.class.getDeclaredField("THE_ONE"); field.setAccessible(true); UNSAFE = (Unsafe) field.get(null); } catch (NoSuchFieldException ex) { throw new RuntimeException(ex); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } } /** * Scribbles on the stack to help ensure we don't have a fake * pointer that would keep would-be garbage alive. */ private static void clearStack(int depth) { int a = 0; int b = 0; int c = 0; int d = 0; int e = 0; int f = 0; int g = 0; int h = 0; int i = 0; int j = 0; if (depth > 0) { clearStack(depth - 1); } } private static class ParkTester extends Thread { public volatile boolean parkNow = false; public volatile boolean success = false; public void run() { while (!parkNow) { try { Thread.sleep(500); } catch (InterruptedException ex) { // Ignore it. } } long start = System.currentTimeMillis(); UNSAFE.park(false, 500 * 1000000); // 500 msec long elapsed = System.currentTimeMillis() - start; if (elapsed > 200) { System.out.println("park()ed for " + elapsed + " msec"); success = false; } else { System.out.println("park() returned quickly"); success = true; } } } }