1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import sun.misc.Unsafe;
18 
19 import java.lang.reflect.Field;
20 
21 public class Main {
22     private static Unsafe UNSAFE;
23 
main(String[] args)24     public static void main(String[] args) throws Exception {
25         setUp();
26 
27         ParkTester test = new ParkTester();
28 
29         System.out.println("Test starting");
30 
31         test.start();
32         UNSAFE.unpark(test);
33         clearStack(10);
34 
35         System.out.println("GC'ing");
36         System.gc();
37         System.runFinalization();
38         System.gc();
39 
40         System.out.println("Asking thread to park");
41         test.parkNow = true;
42 
43         try {
44             // Give some time to the ParkTester thread to honor the park command.
45             Thread.sleep(3000);
46         } catch (InterruptedException ex) {
47             System.out.println("Main thread interrupted!");
48             System.exit(1);
49         }
50 
51         if (test.success) {
52             System.out.println("Test succeeded!");
53         } else {
54             System.out.println("Test failed.");
55         }
56     }
57 
58     /**
59      * Set up {@link #UNSAFE}.
60      */
setUp()61     public static void setUp() throws Exception{
62         /*
63          * Subvert the access check to get the unique Unsafe instance.
64          * We can do this because there's no security manager
65          * installed when running the test.
66          */
67         Field field = null;
68         try {
69             field = Unsafe.class.getDeclaredField("THE_ONE");
70         } catch (NoSuchFieldException e1) {
71             try {
72                 field = Unsafe.class.getDeclaredField("theUnsafe");
73             } catch (NoSuchFieldException e2) {
74                 throw new RuntimeException("Failed to find THE_ONE or theUnsafe");
75             }
76         }
77         field.setAccessible(true);
78         UNSAFE = (Unsafe) field.get(null);
79     }
80 
81     /**
82      * Scribbles on the stack to help ensure we don't have a fake
83      * pointer that would keep would-be garbage alive.
84      */
clearStack(int depth)85     private static void clearStack(int depth) {
86         int a = 0;
87         int b = 0;
88         int c = 0;
89         int d = 0;
90         int e = 0;
91         int f = 0;
92         int g = 0;
93         int h = 0;
94         int i = 0;
95         int j = 0;
96 
97         if (depth > 0) {
98             clearStack(depth - 1);
99         }
100     }
101 
102     private static class ParkTester extends Thread {
103         public volatile boolean parkNow = false;
104         public volatile boolean success = false;
105 
run()106         public void run() {
107             while (!parkNow) {
108                 try {
109                     Thread.sleep(500);
110                 } catch (InterruptedException ex) {
111                     // Ignore it.
112                 }
113             }
114 
115             long start = System.currentTimeMillis();
116             UNSAFE.park(false, 500 * 1000000); // 500 msec
117             long elapsed = System.currentTimeMillis() - start;
118 
119             if (elapsed > 200) {
120                 System.out.println("park()ed for " + elapsed + " msec");
121                 success = false;
122             } else {
123                 System.out.println("park() returned quickly");
124                 success = true;
125             }
126         }
127     }
128 }
129