Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2015 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 java.lang.reflect.Field;
     18 import java.lang.reflect.Method;
     19 import java.util.List;
     20 import p1.InP1;
     21 import p1.PlaceHolder;
     22 
     23 
     24 // Custom class loader to prevent loading while verifying.
     25 class MyClassLoader extends ClassLoader {
     26   MyClassLoader() throws Exception {
     27     super(MyClassLoader.class.getClassLoader());
     28 
     29     // Some magic to get access to the pathList field of BaseDexClassLoader.
     30     ClassLoader loader = getClass().getClassLoader();
     31     Class<?> baseDexClassLoader = loader.getClass().getSuperclass();
     32     Field f = baseDexClassLoader.getDeclaredField("pathList");
     33     f.setAccessible(true);
     34     Object pathList = f.get(loader);
     35 
     36     // Some magic to get access to the dexField field of pathList.
     37     f = pathList.getClass().getDeclaredField("dexElements");
     38     f.setAccessible(true);
     39     dexElements = (Object[]) f.get(pathList);
     40     dexFileField = dexElements[0].getClass().getDeclaredField("dexFile");
     41     dexFileField.setAccessible(true);
     42   }
     43 
     44   Object[] dexElements;
     45   Field dexFileField;
     46 
     47   protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
     48     if (className.equals("p1.OtherInP1") && !p1.PlaceHolder.entered) {
     49       // The request comes from the verifier. Return null to get the access check entry
     50       // point in the compiled code.
     51       return null;
     52     }
     53     // Mimic what DexPathList.findClass is doing.
     54     try {
     55       for (Object element : dexElements) {
     56         Object dex = dexFileField.get(element);
     57         Method method = dex.getClass().getDeclaredMethod(
     58             "loadClassBinaryName", String.class, ClassLoader.class, List.class);
     59 
     60         if (dex != null) {
     61           Class<?> clazz = (Class<?>)method.invoke(dex, className, this, null);
     62           if (clazz != null) {
     63             return clazz;
     64           }
     65         }
     66       }
     67     } catch (Exception e) { /* Ignore */ }
     68     return getParent().loadClass(className);
     69   }
     70 }
     71 
     72 public class Main {
     73     public static void main(String[] args) throws Exception {
     74       MyClassLoader o = new MyClassLoader();
     75       Class<?> foo = o.loadClass("LoadedByMyClassLoader");
     76       Method m = foo.getDeclaredMethod("main");
     77       m.invoke(null);
     78     }
     79 }
     80 
     81 class LoadedByMyClassLoader {
     82     public static void main() throws Exception {
     83       for (int i = 0; i < 10000; ++i) {
     84         // Warm up the JIT.
     85         doTheCall(i);
     86       }
     87       // Sleep a while to let the JIT compile things.
     88       // TODO(ngeoffray): Remove the sleep. b/25414532
     89       Thread.sleep(2000);
     90       doTheCall(10001);
     91     }
     92 
     93     public static void doTheCall(int i) {
     94       InP1.$inline$AllocateOtherInP1(i);
     95       InP1.$inline$AllocateArrayOtherInP1(i);
     96       InP1.$inline$UseStaticFieldOtherInP1(i);
     97       InP1.$inline$SetStaticFieldOtherInP1(i);
     98       InP1.$inline$UseInstanceFieldOtherInP1(i);
     99       InP1.$inline$SetInstanceFieldOtherInP1(i);
    100       InP1.$inline$LoadOtherInP1(i);
    101       InP1.$inline$StaticCallOtherInP1(i);
    102       InP1.$inline$InstanceCallOtherInP1(i);
    103     }
    104 }
    105