Home | History | Annotate | Download | only in src
      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 
     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      */
     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      */
     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 
    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