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. registerAsParallelCapable()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 RacyLoader(ClassLoader parent, int count)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 findClass(String name)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 loadClass(String name, boolean resolve)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 syncWithOtherInstances(int limit)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