Main.java revision 2ad60cfc28e14ee8f0bb038720836a4696c478ad
1import sun.misc.Unsafe;
2
3import java.lang.reflect.Field;
4
5public 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.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     */
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     */
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
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