Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2016 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 public class RacyMisbehavingLoader extends DefiningLoader {
     18     static {
     19         // For JVM, register as parallel capable.
     20         // Android treats all class loaders as parallel capable and makes this a no-op.
     21         registerAsParallelCapable();
     22     }
     23 
     24     private Object lock = new Object();
     25     private int index = 0;
     26     private int count;
     27     private boolean throw_error;
     28 
     29     private DefiningLoader[] defining_loaders;
     30 
     31     public RacyMisbehavingLoader(ClassLoader parent, int count, boolean throw_error) {
     32         super(parent);
     33         this.count = count;
     34         this.throw_error = throw_error;
     35         defining_loaders = new DefiningLoader[2];
     36         for (int i = 0; i != defining_loaders.length; ++i) {
     37             defining_loaders[i] = new DefiningLoader(parent);
     38         }
     39     }
     40 
     41     public void reportAfterLoading() {
     42         synchronized (lock) {
     43             ++index;
     44             if (index == 2 * count) {
     45                 lock.notifyAll();
     46             }
     47         }
     48     }
     49 
     50     protected Class<?> findClass(String name) throws ClassNotFoundException
     51     {
     52         if (name.equals("Test")) {
     53             throw new Error("Unexpected RacyLoader.findClass(\"" + name + "\")");
     54         }
     55         return super.findClass(name);
     56     }
     57 
     58     protected Class<?> loadClass(String name, boolean resolve)
     59         throws ClassNotFoundException
     60     {
     61         if (name.equals("Test")) {
     62             int my_index = syncWithOtherInstances(count);
     63             Class<?> result;
     64             if ((my_index & 1) == 0) {
     65               // Do not delay loading the correct class.
     66               result = defining_loaders[my_index & 1].loadClass(name, resolve);
     67             } else {
     68               // Delay loading the wrong class.
     69               syncWithOtherInstances(2 * count);
     70               if (throw_error) {
     71                 throw new Error("RacyMisbehavingLoader throw_error=true");
     72               }
     73               result = defining_loaders[my_index & 1].loadClass("Test3", resolve);
     74             }
     75             return result;
     76         }
     77         return super.loadClass(name, resolve);
     78     }
     79 
     80     private int syncWithOtherInstances(int limit) {
     81         int my_index;
     82         synchronized (lock) {
     83             my_index = index;
     84             ++index;
     85             if (index != limit) {
     86                 do {
     87                     try {
     88                         lock.wait();
     89                     } catch (InterruptedException ie) {
     90                         throw new Error(ie);
     91                     }
     92                 } while (index < limit);
     93             } else {
     94                 lock.notifyAll();
     95             }
     96         }
     97         return my_index;
     98     }
     99 }
    100