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 RacyLoader 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 
     28     private DefiningLoader[] defining_loaders;
     29 
     30     public RacyLoader(ClassLoader parent, int count) {
     31         super(parent);
     32         this.count = count;
     33         defining_loaders = new DefiningLoader[2];
     34         for (int i = 0; i != defining_loaders.length; ++i) {
     35             defining_loaders[i] = new DefiningLoader(parent);
     36         }
     37     }
     38 
     39     protected Class<?> findClass(String name) throws ClassNotFoundException
     40     {
     41         if (name.equals("Test") || name.equals("Test3")) {
     42             throw new Error("Unexpected RacyLoader.findClass(\"" + name + "\")");
     43         }
     44         return super.findClass(name);
     45     }
     46 
     47     protected Class<?> loadClass(String name, boolean resolve)
     48         throws ClassNotFoundException
     49     {
     50         if (name.equals("Test") || name.equals("Test3")) {
     51             int my_index = syncWithOtherInstances(count);
     52             Class<?> result = defining_loaders[my_index & 1].loadClass(name, resolve);
     53             syncWithOtherInstances(2 * count);
     54             return result;
     55         }
     56         return super.loadClass(name, resolve);
     57     }
     58 
     59     private int syncWithOtherInstances(int limit) {
     60         int my_index;
     61         synchronized (lock) {
     62             my_index = index;
     63             ++index;
     64             if (index != limit) {
     65                 do {
     66                     try {
     67                         lock.wait();
     68                     } catch (InterruptedException ie) {
     69                         throw new Error(ie);
     70                     }
     71                 } while (index < limit);
     72             } else {
     73                 lock.notifyAll();
     74             }
     75         }
     76         return my_index;
     77     }
     78 }
     79