1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker import art.Redefinition; 18*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Constructor; 19*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method; 20*795d594fSAndroid Build Coastguard Worker import java.net.URL; 21*795d594fSAndroid Build Coastguard Worker import java.net.URLClassLoader; 22*795d594fSAndroid Build Coastguard Worker import java.nio.ByteBuffer; 23*795d594fSAndroid Build Coastguard Worker import java.util.ArrayList; 24*795d594fSAndroid Build Coastguard Worker import java.util.Arrays; 25*795d594fSAndroid Build Coastguard Worker import java.util.Base64; 26*795d594fSAndroid Build Coastguard Worker 27*795d594fSAndroid Build Coastguard Worker public class Main { 28*795d594fSAndroid Build Coastguard Worker private static String TEST_NAME = "1964-add-to-dex-classloader-file"; 29*795d594fSAndroid Build Coastguard Worker private static boolean IS_ART = System.getProperty("java.vm.name").equals("Dalvik"); 30*795d594fSAndroid Build Coastguard Worker 31*795d594fSAndroid Build Coastguard Worker private static String TEST_CLASS_NAME = "foobar.TestClass"; 32*795d594fSAndroid Build Coastguard Worker private static String NEW_CLASS_NAME = "foobar.NewClass"; 33*795d594fSAndroid Build Coastguard Worker 34*795d594fSAndroid Build Coastguard Worker /** 35*795d594fSAndroid Build Coastguard Worker * base64 encoded class/dex file for 36*795d594fSAndroid Build Coastguard Worker * package foobar; 37*795d594fSAndroid Build Coastguard Worker * public class TestClass { 38*795d594fSAndroid Build Coastguard Worker * public static void sayHi() { 39*795d594fSAndroid Build Coastguard Worker * System.out.println("Hello again from TestClass sayHi function"); 40*795d594fSAndroid Build Coastguard Worker * TestClass.sayBye(); 41*795d594fSAndroid Build Coastguard Worker * } 42*795d594fSAndroid Build Coastguard Worker * static void sayBye() { 43*795d594fSAndroid Build Coastguard Worker * System.out.println("Goodbye from TestClass!"); 44*795d594fSAndroid Build Coastguard Worker * } 45*795d594fSAndroid Build Coastguard Worker * } 46*795d594fSAndroid Build Coastguard Worker */ 47*795d594fSAndroid Build Coastguard Worker private static byte[] CLASS_BYTES = Base64.getDecoder().decode( 48*795d594fSAndroid Build Coastguard Worker "yv66vgAAADUAIQoACAARCQASABMIABQKABUAFgoABwAXCAAYBwAZBwAaAQAGPGluaXQ+AQADKClW" 49*795d594fSAndroid Build Coastguard Worker + "AQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEABXNheUhpAQAGc2F5QnllAQAKU291cmNlRmlsZQEA" 50*795d594fSAndroid Build Coastguard Worker + "DlRlc3RDbGFzcy5qYXZhDAAJAAoHABsMABwAHQEAI0hlbGxvIGZyb20gVGVzdENsYXNzIHNheUhp" 51*795d594fSAndroid Build Coastguard Worker + "IGZ1bmN0aW9uBwAeDAAfACAMAA4ACgEAF0dvb2RieWUgZnJvbSBUZXN0Q2xhc3MhAQAQZm9vYmFy" 52*795d594fSAndroid Build Coastguard Worker + "L1Rlc3RDbGFzcwEAEGphdmEvbGFuZy9PYmplY3QBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAV" 53*795d594fSAndroid Build Coastguard Worker + "TGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BABUo" 54*795d594fSAndroid Build Coastguard Worker + "TGphdmEvbGFuZy9TdHJpbmc7KVYAIQAHAAgAAAAAAAMAAQAJAAoAAQALAAAAHQABAAEAAAAFKrcA" 55*795d594fSAndroid Build Coastguard Worker + "AbEAAAABAAwAAAAGAAEAAAACAAkADQAKAAEACwAAACwAAgAAAAAADLIAAhIDtgAEuAAFsQAAAAEA" 56*795d594fSAndroid Build Coastguard Worker + "DAAAAA4AAwAAAAQACAAFAAsABgAIAA4ACgABAAsAAAAlAAIAAAAAAAmyAAISBrYABLEAAAABAAwA" 57*795d594fSAndroid Build Coastguard Worker + "AAAKAAIAAAAIAAgACQABAA8AAAACABA="); 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker private static byte[] DEX_BYTES = Base64.getDecoder().decode( 60*795d594fSAndroid Build Coastguard Worker "ZGV4CjAzNQARmtFTPdWXebnrTNy5b71tEiJKC96qIPXAAwAAcAAAAHhWNBIAAAAAAAAAABQDAAAQ" 61*795d594fSAndroid Build Coastguard Worker + "AAAAcAAAAAYAAACwAAAAAgAAAMgAAAABAAAA4AAAAAUAAADoAAAAAQAAABABAACQAgAAMAEAAKYB" 62*795d594fSAndroid Build Coastguard Worker + "AACuAQAAxwEAAOwBAAAAAgAAFwIAACsCAAA/AgAAUwIAAGMCAABmAgAAagIAAG8CAAB4AgAAgAIA" 63*795d594fSAndroid Build Coastguard Worker + "AIcCAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABQAAAAAAAAAKAAAABQAAAKABAAAEAAEA" 64*795d594fSAndroid Build Coastguard Worker + "CwAAAAAAAAAAAAAAAAAAAA0AAAAAAAAADgAAAAEAAQAMAAAAAgAAAAAAAAAAAAAAAQAAAAIAAAAA" 65*795d594fSAndroid Build Coastguard Worker + "AAAACAAAAAAAAAD+AgAAAAAAAAEAAQABAAAAjgEAAAQAAABwEAQAAAAOAAIAAAACAAAAkgEAAAgA" 66*795d594fSAndroid Build Coastguard Worker + "AABiAAAAGgEBAG4gAwAQAA4AAgAAAAIAAACXAQAACwAAAGIAAAAaAQIAbiADABAAcQABAAAADgAC" 67*795d594fSAndroid Build Coastguard Worker + "AA4ACAAOeAAEAA54PAAAAAABAAAAAwAGPGluaXQ+ABdHb29kYnllIGZyb20gVGVzdENsYXNzIQAj" 68*795d594fSAndroid Build Coastguard Worker + "SGVsbG8gZnJvbSBUZXN0Q2xhc3Mgc2F5SGkgZnVuY3Rpb24AEkxmb29iYXIvVGVzdENsYXNzOwAV" 69*795d594fSAndroid Build Coastguard Worker + "TGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3Ry" 70*795d594fSAndroid Build Coastguard Worker + "aW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AA5UZXN0Q2xhc3MuamF2YQABVgACVkwAA291dAAHcHJp" 71*795d594fSAndroid Build Coastguard Worker + "bnRsbgAGc2F5QnllAAVzYXlIaQB1fn5EOHsiY29tcGlsYXRpb24tbW9kZSI6ImRlYnVnIiwibWlu" 72*795d594fSAndroid Build Coastguard Worker + "LWFwaSI6MSwic2hhLTEiOiJkMzI4MmI4ZjU0N2MyMzRjNGU0YzkzMDljMzZjNzk1YTI5ODU2ZWFi" 73*795d594fSAndroid Build Coastguard Worker + "IiwidmVyc2lvbiI6IjEuNi4xLWRldiJ9AAAAAwAAgYAEsAIBCMgCAQnoAgAAAAAOAAAAAAAAAAEA" 74*795d594fSAndroid Build Coastguard Worker + "AAAAAAAAAQAAABAAAABwAAAAAgAAAAYAAACwAAAAAwAAAAIAAADIAAAABAAAAAEAAADgAAAABQAA" 75*795d594fSAndroid Build Coastguard Worker + "AAUAAADoAAAABgAAAAEAAAAQAQAAASAAAAMAAAAwAQAAAyAAAAMAAACOAQAAARAAAAEAAACgAQAA" 76*795d594fSAndroid Build Coastguard Worker + "AiAAABAAAACmAQAAACAAAAEAAAD+AgAAAxAAAAEAAAAQAwAAABAAAAEAAAAUAwAA"); 77*795d594fSAndroid Build Coastguard Worker /** 78*795d594fSAndroid Build Coastguard Worker * base64 encoded class/dex file for 79*795d594fSAndroid Build Coastguard Worker * package foobar; 80*795d594fSAndroid Build Coastguard Worker * public class TestClass { 81*795d594fSAndroid Build Coastguard Worker * public static void sayHi() { 82*795d594fSAndroid Build Coastguard Worker * System.out.println("Hello again from TestClass sayHi function"); 83*795d594fSAndroid Build Coastguard Worker * NewClass.sayHi(); 84*795d594fSAndroid Build Coastguard Worker * } 85*795d594fSAndroid Build Coastguard Worker * static void sayBye() { 86*795d594fSAndroid Build Coastguard Worker * System.out.println("Goodbye again from TestClass!"); 87*795d594fSAndroid Build Coastguard Worker * } 88*795d594fSAndroid Build Coastguard Worker * } 89*795d594fSAndroid Build Coastguard Worker */ 90*795d594fSAndroid Build Coastguard Worker private static byte[] REDEF_CLASS_BYTES = Base64.getDecoder().decode( 91*795d594fSAndroid Build Coastguard Worker "yv66vgAAADUAIwoACAARCQASABMIABQKABUAFgoAFwAYCAAZBwAaBwAbAQAGPGluaXQ+AQADKClW" 92*795d594fSAndroid Build Coastguard Worker + "AQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEABXNheUhpAQAGc2F5QnllAQAKU291cmNlRmlsZQEA" 93*795d594fSAndroid Build Coastguard Worker + "DlRlc3RDbGFzcy5qYXZhDAAJAAoHABwMAB0AHgEAKUhlbGxvIGFnYWluIGZyb20gVGVzdENsYXNz" 94*795d594fSAndroid Build Coastguard Worker + "IHNheUhpIGZ1bmN0aW9uBwAfDAAgACEHACIMAA0ACgEAHUdvb2RieWUgYWdhaW4gZnJvbSBUZXN0" 95*795d594fSAndroid Build Coastguard Worker + "Q2xhc3MhAQAQZm9vYmFyL1Rlc3RDbGFzcwEAEGphdmEvbGFuZy9PYmplY3QBABBqYXZhL2xhbmcv" 96*795d594fSAndroid Build Coastguard Worker + "U3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2YS9pby9QcmludFN0cmVh" 97*795d594fSAndroid Build Coastguard Worker + "bQEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAA9mb29iYXIvTmV3Q2xhc3MAIQAH" 98*795d594fSAndroid Build Coastguard Worker + "AAgAAAAAAAMAAQAJAAoAAQALAAAAHQABAAEAAAAFKrcAAbEAAAABAAwAAAAGAAEAAAACAAkADQAK" 99*795d594fSAndroid Build Coastguard Worker + "AAEACwAAACwAAgAAAAAADLIAAhIDtgAEuAAFsQAAAAEADAAAAA4AAwAAAAQACAAFAAsABgAIAA4A" 100*795d594fSAndroid Build Coastguard Worker + "CgABAAsAAAAlAAIAAAAAAAmyAAISBrYABLEAAAABAAwAAAAKAAIAAAAIAAgACQABAA8AAAACABA="); 101*795d594fSAndroid Build Coastguard Worker 102*795d594fSAndroid Build Coastguard Worker private static byte[] REDEF_DEX_BYTES = Base64.getDecoder().decode( 103*795d594fSAndroid Build Coastguard Worker "ZGV4CjAzNQA2plEeYRH4vl6wJgnAZOVcZ537QN9NXB3wAwAAcAAAAHhWNBIAAAAAAAAAAEQDAAAR" 104*795d594fSAndroid Build Coastguard Worker + "AAAAcAAAAAcAAAC0AAAAAgAAANAAAAABAAAA6AAAAAYAAADwAAAAAQAAACABAACwAgAAQAEAALYB" 105*795d594fSAndroid Build Coastguard Worker + "AAC+AQAA3QEAAAgCAAAbAgAALwIAAEYCAABaAgAAbgIAAIICAACSAgAAlQIAAJkCAACeAgAApwIA" 106*795d594fSAndroid Build Coastguard Worker + "AK8CAAC2AgAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACgAAAAoAAAAGAAAAAAAAAAsAAAAGAAAA" 107*795d594fSAndroid Build Coastguard Worker + "sAEAAAUAAgAMAAAAAAAAAA8AAAABAAAAAAAAAAEAAAAOAAAAAQAAAA8AAAACAAEADQAAAAMAAAAA" 108*795d594fSAndroid Build Coastguard Worker + "AAAAAQAAAAEAAAADAAAAAAAAAAkAAAAAAAAALQMAAAAAAAABAAEAAQAAAJ4BAAAEAAAAcBAFAAAA" 109*795d594fSAndroid Build Coastguard Worker + "DgACAAAAAgAAAKIBAAAIAAAAYgAAABoBAQBuIAQAEAAOAAIAAAACAAAApwEAAAsAAABiAAAAGgEC" 110*795d594fSAndroid Build Coastguard Worker + "AG4gBAAQAHEAAAAAAA4AAgAOAAgADngABAAOeDwAAAAAAQAAAAQABjxpbml0PgAdR29vZGJ5ZSBh" 111*795d594fSAndroid Build Coastguard Worker + "Z2FpbiBmcm9tIFRlc3RDbGFzcyEAKUhlbGxvIGFnYWluIGZyb20gVGVzdENsYXNzIHNheUhpIGZ1" 112*795d594fSAndroid Build Coastguard Worker + "bmN0aW9uABFMZm9vYmFyL05ld0NsYXNzOwASTGZvb2Jhci9UZXN0Q2xhc3M7ABVMamF2YS9pby9Q" 113*795d594fSAndroid Build Coastguard Worker + "cmludFN0cmVhbTsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABJMamF2" 114*795d594fSAndroid Build Coastguard Worker + "YS9sYW5nL1N5c3RlbTsADlRlc3RDbGFzcy5qYXZhAAFWAAJWTAADb3V0AAdwcmludGxuAAZzYXlC" 115*795d594fSAndroid Build Coastguard Worker + "eWUABXNheUhpAHV+fkQ4eyJjb21waWxhdGlvbi1tb2RlIjoiZGVidWciLCJtaW4tYXBpIjoxLCJz" 116*795d594fSAndroid Build Coastguard Worker + "aGEtMSI6ImQzMjgyYjhmNTQ3YzIzNGM0ZTRjOTMwOWMzNmM3OTVhMjk4NTZlYWIiLCJ2ZXJzaW9u" 117*795d594fSAndroid Build Coastguard Worker + "IjoiMS42LjEtZGV2In0AAAADAAGBgATAAgEI2AIBCfgCAAAAAAAOAAAAAAAAAAEAAAAAAAAAAQAA" 118*795d594fSAndroid Build Coastguard Worker + "ABEAAABwAAAAAgAAAAcAAAC0AAAAAwAAAAIAAADQAAAABAAAAAEAAADoAAAABQAAAAYAAADwAAAA" 119*795d594fSAndroid Build Coastguard Worker + "BgAAAAEAAAAgAQAAASAAAAMAAABAAQAAAyAAAAMAAACeAQAAARAAAAEAAACwAQAAAiAAABEAAAC2" 120*795d594fSAndroid Build Coastguard Worker + "AQAAACAAAAEAAAAtAwAAAxAAAAEAAABAAwAAABAAAAEAAABEAwAA"); 121*795d594fSAndroid Build Coastguard Worker SafePrintCause(Throwable t)122*795d594fSAndroid Build Coastguard Worker public static void SafePrintCause(Throwable t) { 123*795d594fSAndroid Build Coastguard Worker StackTraceElement cause = t.getStackTrace()[0]; 124*795d594fSAndroid Build Coastguard Worker System.out.println(" --- " + t.getClass().getName() + " At " + cause.getClassName() + "." + 125*795d594fSAndroid Build Coastguard Worker cause.getMethodName() + "(" + cause.getFileName() + ":" + 126*795d594fSAndroid Build Coastguard Worker cause.getLineNumber() + ")"); 127*795d594fSAndroid Build Coastguard Worker } 128*795d594fSAndroid Build Coastguard Worker run()129*795d594fSAndroid Build Coastguard Worker public static void run() throws Exception { 130*795d594fSAndroid Build Coastguard Worker System.out.println(" - Run while adding new referenced class."); 131*795d594fSAndroid Build Coastguard Worker try { 132*795d594fSAndroid Build Coastguard Worker run(true); 133*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 134*795d594fSAndroid Build Coastguard Worker // Unfortunately art and RI have different messages here so just return the type. 135*795d594fSAndroid Build Coastguard Worker System.out.println(" -- Exception caught when running test with new class added! " + 136*795d594fSAndroid Build Coastguard Worker e.getCause().getClass().getName()); 137*795d594fSAndroid Build Coastguard Worker SafePrintCause(e.getCause()); 138*795d594fSAndroid Build Coastguard Worker System.out.println(e); 139*795d594fSAndroid Build Coastguard Worker e.printStackTrace(); 140*795d594fSAndroid Build Coastguard Worker } 141*795d594fSAndroid Build Coastguard Worker System.out.println(" - Run without adding new referenced class."); 142*795d594fSAndroid Build Coastguard Worker try { 143*795d594fSAndroid Build Coastguard Worker run(false); 144*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 145*795d594fSAndroid Build Coastguard Worker // Unfortunately art and RI have different messages here so just return the type. 146*795d594fSAndroid Build Coastguard Worker System.out.println(" -- Exception caught when running test without new class added! " + 147*795d594fSAndroid Build Coastguard Worker e.getCause().getClass().getName()); 148*795d594fSAndroid Build Coastguard Worker SafePrintCause(e.getCause()); 149*795d594fSAndroid Build Coastguard Worker } 150*795d594fSAndroid Build Coastguard Worker } 151*795d594fSAndroid Build Coastguard Worker run(boolean add_new)152*795d594fSAndroid Build Coastguard Worker public static void run(boolean add_new) throws Exception { 153*795d594fSAndroid Build Coastguard Worker ClassLoader cl = getClassLoader(); 154*795d594fSAndroid Build Coastguard Worker Class<?> target = cl.loadClass(TEST_CLASS_NAME); 155*795d594fSAndroid Build Coastguard Worker Method sayHi = target.getDeclaredMethod("sayHi"); 156*795d594fSAndroid Build Coastguard Worker System.out.println(" -- Running sayHi before redefinition"); 157*795d594fSAndroid Build Coastguard Worker sayHi.invoke(null); 158*795d594fSAndroid Build Coastguard Worker if (add_new) { 159*795d594fSAndroid Build Coastguard Worker System.out.println(" -- Adding NewClass to classloader!"); 160*795d594fSAndroid Build Coastguard Worker addToClassLoader(cl); 161*795d594fSAndroid Build Coastguard Worker } 162*795d594fSAndroid Build Coastguard Worker System.out.println(" -- Redefine the TestClass"); 163*795d594fSAndroid Build Coastguard Worker Redefinition.doCommonClassRedefinition(target, REDEF_CLASS_BYTES, REDEF_DEX_BYTES); 164*795d594fSAndroid Build Coastguard Worker System.out.println(" -- call TestClass again, now with NewClass refs"); 165*795d594fSAndroid Build Coastguard Worker sayHi.invoke(null); 166*795d594fSAndroid Build Coastguard Worker } 167*795d594fSAndroid Build Coastguard Worker 168*795d594fSAndroid Build Coastguard Worker public static class ExtensibleClassLoader extends URLClassLoader { ExtensibleClassLoader()169*795d594fSAndroid Build Coastguard Worker public ExtensibleClassLoader() { 170*795d594fSAndroid Build Coastguard Worker // Initially we don't have any URLs 171*795d594fSAndroid Build Coastguard Worker super(new URL[] {}, ExtensibleClassLoader.class.getClassLoader()); 172*795d594fSAndroid Build Coastguard Worker } 173*795d594fSAndroid Build Coastguard Worker addSingleUrl(String file)174*795d594fSAndroid Build Coastguard Worker public void addSingleUrl(String file) throws Exception { 175*795d594fSAndroid Build Coastguard Worker this.addURL(new URL("file://" + file)); 176*795d594fSAndroid Build Coastguard Worker } 177*795d594fSAndroid Build Coastguard Worker findClass(String name)178*795d594fSAndroid Build Coastguard Worker protected Class<?> findClass(String name) throws ClassNotFoundException { 179*795d594fSAndroid Build Coastguard Worker // Just define the TestClass without other jars. 180*795d594fSAndroid Build Coastguard Worker if (name.equals(TEST_CLASS_NAME)) { 181*795d594fSAndroid Build Coastguard Worker return this.defineClass(TEST_CLASS_NAME, CLASS_BYTES, 0, CLASS_BYTES.length); 182*795d594fSAndroid Build Coastguard Worker } else { 183*795d594fSAndroid Build Coastguard Worker return super.findClass(name); 184*795d594fSAndroid Build Coastguard Worker } 185*795d594fSAndroid Build Coastguard Worker } 186*795d594fSAndroid Build Coastguard Worker } 187*795d594fSAndroid Build Coastguard Worker getClassLoader()188*795d594fSAndroid Build Coastguard Worker public static ClassLoader getClassLoader() throws Exception { 189*795d594fSAndroid Build Coastguard Worker if (!IS_ART) { 190*795d594fSAndroid Build Coastguard Worker return new ExtensibleClassLoader(); 191*795d594fSAndroid Build Coastguard Worker } else { 192*795d594fSAndroid Build Coastguard Worker Class<?> class_loader_class = Class.forName("dalvik.system.InMemoryDexClassLoader"); 193*795d594fSAndroid Build Coastguard Worker Constructor<?> ctor = class_loader_class.getConstructor(ByteBuffer.class, ClassLoader.class); 194*795d594fSAndroid Build Coastguard Worker return (ClassLoader)ctor.newInstance(ByteBuffer.wrap(DEX_BYTES), Main.class.getClassLoader()); 195*795d594fSAndroid Build Coastguard Worker } 196*795d594fSAndroid Build Coastguard Worker } 197*795d594fSAndroid Build Coastguard Worker addToClassLoader(ClassLoader cl)198*795d594fSAndroid Build Coastguard Worker public static void addToClassLoader(ClassLoader cl) throws Exception { 199*795d594fSAndroid Build Coastguard Worker if (IS_ART) { 200*795d594fSAndroid Build Coastguard Worker addToClassLoaderNative(cl, System.getenv("DEX_LOCATION") + "/" + TEST_NAME + "-ex.jar"); 201*795d594fSAndroid Build Coastguard Worker } else { 202*795d594fSAndroid Build Coastguard Worker ((ExtensibleClassLoader)cl).addSingleUrl(System.getenv("DEX_LOCATION") + "/classes-ex/"); 203*795d594fSAndroid Build Coastguard Worker } 204*795d594fSAndroid Build Coastguard Worker } 205*795d594fSAndroid Build Coastguard Worker addToClassLoaderNative(ClassLoader loader, String segment)206*795d594fSAndroid Build Coastguard Worker public static native void addToClassLoaderNative(ClassLoader loader, String segment); main(String[] args)207*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Exception { 208*795d594fSAndroid Build Coastguard Worker run(); 209*795d594fSAndroid Build Coastguard Worker } 210*795d594fSAndroid Build Coastguard Worker } 211