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.Method; 19*795d594fSAndroid Build Coastguard Worker import java.util.Arrays; 20*795d594fSAndroid Build Coastguard Worker import java.util.Base64; 21*795d594fSAndroid Build Coastguard Worker import java.util.concurrent.CountDownLatch; 22*795d594fSAndroid Build Coastguard Worker import java.util.concurrent.Phaser; 23*795d594fSAndroid Build Coastguard Worker import java.util.function.Consumer; 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker public class Main { 26*795d594fSAndroid Build Coastguard Worker public static final int NUM_THREADS = 10; 27*795d594fSAndroid Build Coastguard Worker public static final boolean PRINT = false; 28*795d594fSAndroid Build Coastguard Worker 29*795d594fSAndroid Build Coastguard Worker // import java.util.function.Consumer; 30*795d594fSAndroid Build Coastguard Worker // 31*795d594fSAndroid Build Coastguard Worker // class Transform { 32*795d594fSAndroid Build Coastguard Worker // public void sayHi(Consumer<Consumer<String>> r, Consumer<String> reporter) { 33*795d594fSAndroid Build Coastguard Worker // reporter.accept("goodbye - Start method sayHi"); 34*795d594fSAndroid Build Coastguard Worker // r.accept(reporter); 35*795d594fSAndroid Build Coastguard Worker // reporter.accept("goodbye - End method sayHi"); 36*795d594fSAndroid Build Coastguard Worker // } 37*795d594fSAndroid Build Coastguard Worker // } 38*795d594fSAndroid Build Coastguard Worker private static final byte[] CLASS_BYTES = Base64.getDecoder().decode( 39*795d594fSAndroid Build Coastguard Worker "yv66vgAAADUAGwoABgARCAASCwATABQIABUHABYHABcBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAP" 40*795d594fSAndroid Build Coastguard Worker + "TGluZU51bWJlclRhYmxlAQAFc2F5SGkBAD0oTGphdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjtM" 41*795d594fSAndroid Build Coastguard Worker + "amF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyOylWAQAJU2lnbmF0dXJlAQCEKExqYXZhL3V0aWwv" 42*795d594fSAndroid Build Coastguard Worker + "ZnVuY3Rpb24vQ29uc3VtZXI8TGphdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjxMamF2YS9sYW5n" 43*795d594fSAndroid Build Coastguard Worker + "L1N0cmluZzs+Oz47TGphdmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjxMamF2YS9sYW5nL1N0cmlu" 44*795d594fSAndroid Build Coastguard Worker + "Zzs+OylWAQAKU291cmNlRmlsZQEADlRyYW5zZm9ybS5qYXZhDAAHAAgBABxnb29kYnllIC0gU3Rh" 45*795d594fSAndroid Build Coastguard Worker + "cnQgbWV0aG9kIHNheUhpBwAYDAAZABoBABpnb29kYnllIC0gRW5kIG1ldGhvZCBzYXlIaQEACVRy" 46*795d594fSAndroid Build Coastguard Worker + "YW5zZm9ybQEAEGphdmEvbGFuZy9PYmplY3QBABtqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXIB" 47*795d594fSAndroid Build Coastguard Worker + "AAZhY2NlcHQBABUoTGphdmEvbGFuZy9PYmplY3Q7KVYAIAAFAAYAAAAAAAIAAAAHAAgAAQAJAAAA" 48*795d594fSAndroid Build Coastguard Worker + "HQABAAEAAAAFKrcAAbEAAAABAAoAAAAGAAEAAAAHAAEACwAMAAIACQAAADwAAgADAAAAGCwSArkA" 49*795d594fSAndroid Build Coastguard Worker + "AwIAKyy5AAMCACwSBLkAAwIAsQAAAAEACgAAABIABAAAAAkACAAKAA8ACwAXAAwADQAAAAIADgAB" 50*795d594fSAndroid Build Coastguard Worker + "AA8AAAACABA="); 51*795d594fSAndroid Build Coastguard Worker 52*795d594fSAndroid Build Coastguard Worker private static final byte[] DEX_BYTES = Base64.getDecoder().decode( 53*795d594fSAndroid Build Coastguard Worker "ZGV4CjAzNQA8rBr8fYSjBsIDrOiAknAnKu+2xbIe3RAsBAAAcAAAAHhWNBIAAAAAAAAAAHQDAAAU" 54*795d594fSAndroid Build Coastguard Worker + "AAAAcAAAAAUAAADAAAAAAwAAANQAAAAAAAAAAAAAAAQAAAD4AAAAAQAAABgBAAD0AgAAOAEAAJwB" 55*795d594fSAndroid Build Coastguard Worker + "AACfAQAApwEAAK0BAACzAQAAwAEAAN8BAADzAQAABwIAACYCAABFAgAAVQIAAFgCAABcAgAAYQIA" 56*795d594fSAndroid Build Coastguard Worker + "AGkCAACFAgAAowIAAKoCAACxAgAABAAAAAUAAAAGAAAACAAAAAsAAAALAAAABAAAAAAAAAAMAAAA" 57*795d594fSAndroid Build Coastguard Worker + "BAAAAIwBAAANAAAABAAAAJQBAAAAAAAAAQAAAAAAAgARAAAAAgAAAAEAAAADAAEADgAAAAAAAAAA" 58*795d594fSAndroid Build Coastguard Worker + "AAAAAgAAAAAAAAAKAAAAXAMAAD8DAAAAAAAAAQABAAEAAAB8AQAABAAAAHAQAgAAAA4ABAADAAIA" 59*795d594fSAndroid Build Coastguard Worker + "AACAAQAADgAAABoAEAByIAMAAwByIAMAMgAaAg8AciADACMADgAHAA4ACQIAAA5aPFoAAAAAAQAA" 60*795d594fSAndroid Build Coastguard Worker + "AAIAAAACAAAAAwADAAEoAAY8aW5pdD4ABD47KVYABD47PjsAC0xUcmFuc2Zvcm07AB1MZGFsdmlr" 61*795d594fSAndroid Build Coastguard Worker + "L2Fubm90YXRpb24vU2lnbmF0dXJlOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0" 62*795d594fSAndroid Build Coastguard Worker + "cmluZzsAHUxqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI7AB1MamF2YS91dGlsL2Z1bmN0aW9u" 63*795d594fSAndroid Build Coastguard Worker + "L0NvbnN1bWVyPAAOVHJhbnNmb3JtLmphdmEAAVYAAlZMAANWTEwABmFjY2VwdAAaZ29vZGJ5ZSAt" 64*795d594fSAndroid Build Coastguard Worker + "IEVuZCBtZXRob2Qgc2F5SGkAHGdvb2RieWUgLSBTdGFydCBtZXRob2Qgc2F5SGkABXNheUhpAAV2" 65*795d594fSAndroid Build Coastguard Worker + "YWx1ZQB2fn5EOHsiY29tcGlsYXRpb24tbW9kZSI6ImRlYnVnIiwibWluLWFwaSI6MSwic2hhLTEi" 66*795d594fSAndroid Build Coastguard Worker + "OiI3MTExYTM1YmFlNmQ1MTg1ZGNmYjMzOGQ2MTA3NGFjYTg0MjZjMDA2IiwidmVyc2lvbiI6IjEu" 67*795d594fSAndroid Build Coastguard Worker + "NS4xNC1kZXYifQACAQESHAgXABcJFwkXBxcDFwkXBxcCAAABAQCAgAS4AgEB0AIAAAAAAAAAAQAA" 68*795d594fSAndroid Build Coastguard Worker + "ACkDAABQAwAAAAAAAAEAAAAAAAAAAQAAAFQDAAAPAAAAAAAAAAEAAAAAAAAAAQAAABQAAABwAAAA" 69*795d594fSAndroid Build Coastguard Worker + "AgAAAAUAAADAAAAAAwAAAAMAAADUAAAABQAAAAQAAAD4AAAABgAAAAEAAAAYAQAAASAAAAIAAAA4" 70*795d594fSAndroid Build Coastguard Worker + "AQAAAyAAAAIAAAB8AQAAARAAAAIAAACMAQAAAiAAABQAAACcAQAABCAAAAEAAAApAwAAACAAAAEA" 71*795d594fSAndroid Build Coastguard Worker + "AAA/AwAAAxAAAAIAAABQAwAABiAAAAEAAABcAwAAABAAAAEAAAB0AwAA"); 72*795d594fSAndroid Build Coastguard Worker 73*795d594fSAndroid Build Coastguard Worker // A class that we can use to keep track of the output of this test. 74*795d594fSAndroid Build Coastguard Worker private static class TestWatcher implements Consumer<String> { 75*795d594fSAndroid Build Coastguard Worker private StringBuilder sb; 76*795d594fSAndroid Build Coastguard Worker private String thread; TestWatcher(String thread)77*795d594fSAndroid Build Coastguard Worker public TestWatcher(String thread) { 78*795d594fSAndroid Build Coastguard Worker sb = new StringBuilder(); 79*795d594fSAndroid Build Coastguard Worker this.thread = thread; 80*795d594fSAndroid Build Coastguard Worker } 81*795d594fSAndroid Build Coastguard Worker 82*795d594fSAndroid Build Coastguard Worker @Override accept(String s)83*795d594fSAndroid Build Coastguard Worker public void accept(String s) { 84*795d594fSAndroid Build Coastguard Worker String msg = thread + ": \t" + s; 85*795d594fSAndroid Build Coastguard Worker maybePrint(msg); 86*795d594fSAndroid Build Coastguard Worker sb.append(msg); 87*795d594fSAndroid Build Coastguard Worker sb.append('\n'); 88*795d594fSAndroid Build Coastguard Worker } 89*795d594fSAndroid Build Coastguard Worker getOutput()90*795d594fSAndroid Build Coastguard Worker public String getOutput() { 91*795d594fSAndroid Build Coastguard Worker return sb.toString(); 92*795d594fSAndroid Build Coastguard Worker } 93*795d594fSAndroid Build Coastguard Worker clear()94*795d594fSAndroid Build Coastguard Worker public void clear() { 95*795d594fSAndroid Build Coastguard Worker sb = new StringBuilder(); 96*795d594fSAndroid Build Coastguard Worker } 97*795d594fSAndroid Build Coastguard Worker } 98*795d594fSAndroid Build Coastguard Worker main(String[] args)99*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Exception { 100*795d594fSAndroid Build Coastguard Worker doTest(new Transform()); 101*795d594fSAndroid Build Coastguard Worker } 102*795d594fSAndroid Build Coastguard Worker 103*795d594fSAndroid Build Coastguard Worker private static boolean interpreting = true; 104*795d594fSAndroid Build Coastguard Worker doTest(Transform t)105*795d594fSAndroid Build Coastguard Worker public static void doTest(Transform t) throws Exception { 106*795d594fSAndroid Build Coastguard Worker TestWatcher[] watchers = new TestWatcher[NUM_THREADS]; 107*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < NUM_THREADS; i++) { 108*795d594fSAndroid Build Coastguard Worker watchers[i] = new TestWatcher("Thread " + i); 109*795d594fSAndroid Build Coastguard Worker } 110*795d594fSAndroid Build Coastguard Worker 111*795d594fSAndroid Build Coastguard Worker // This just prints something out to show we are running the Runnable. 112*795d594fSAndroid Build Coastguard Worker Consumer<Consumer<String>> say_nothing = (Consumer<String> w) -> { 113*795d594fSAndroid Build Coastguard Worker w.accept("Not doing anything here"); 114*795d594fSAndroid Build Coastguard Worker }; 115*795d594fSAndroid Build Coastguard Worker 116*795d594fSAndroid Build Coastguard Worker // Run ensureJitCompiled here since it might get GCd 117*795d594fSAndroid Build Coastguard Worker ensureJitCompiled(Transform.class, "sayHi"); 118*795d594fSAndroid Build Coastguard Worker final CountDownLatch arrive = new CountDownLatch(NUM_THREADS); 119*795d594fSAndroid Build Coastguard Worker final CountDownLatch depart = new CountDownLatch(1); 120*795d594fSAndroid Build Coastguard Worker Consumer<Consumer<String>> request_redefine = (Consumer<String> w) -> { 121*795d594fSAndroid Build Coastguard Worker try { 122*795d594fSAndroid Build Coastguard Worker arrive.countDown(); 123*795d594fSAndroid Build Coastguard Worker w.accept("Requesting redefinition"); 124*795d594fSAndroid Build Coastguard Worker depart.await(); 125*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 126*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Failed to do something", e); 127*795d594fSAndroid Build Coastguard Worker } 128*795d594fSAndroid Build Coastguard Worker }; 129*795d594fSAndroid Build Coastguard Worker Thread redefinition_thread = new RedefinitionThread(arrive, depart); 130*795d594fSAndroid Build Coastguard Worker redefinition_thread.start(); 131*795d594fSAndroid Build Coastguard Worker Thread[] threads = new Thread[NUM_THREADS]; 132*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < NUM_THREADS; i++) { 133*795d594fSAndroid Build Coastguard Worker threads[i] = new TestThread(t, watchers[i], say_nothing, request_redefine); 134*795d594fSAndroid Build Coastguard Worker threads[i].start(); 135*795d594fSAndroid Build Coastguard Worker } 136*795d594fSAndroid Build Coastguard Worker redefinition_thread.join(); 137*795d594fSAndroid Build Coastguard Worker Arrays.stream(threads).forEach((thr) -> { 138*795d594fSAndroid Build Coastguard Worker try { 139*795d594fSAndroid Build Coastguard Worker thr.join(); 140*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 141*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Failed to join: ", e); 142*795d594fSAndroid Build Coastguard Worker } 143*795d594fSAndroid Build Coastguard Worker }); 144*795d594fSAndroid Build Coastguard Worker Arrays.stream(watchers).forEach((w) -> { System.out.println(w.getOutput()); }); 145*795d594fSAndroid Build Coastguard Worker } 146*795d594fSAndroid Build Coastguard Worker 147*795d594fSAndroid Build Coastguard Worker private static class RedefinitionThread extends Thread { 148*795d594fSAndroid Build Coastguard Worker private CountDownLatch arrivalLatch; 149*795d594fSAndroid Build Coastguard Worker private CountDownLatch departureLatch; RedefinitionThread(CountDownLatch arrival, CountDownLatch departure)150*795d594fSAndroid Build Coastguard Worker public RedefinitionThread(CountDownLatch arrival, CountDownLatch departure) { 151*795d594fSAndroid Build Coastguard Worker super("Redefine thread!"); 152*795d594fSAndroid Build Coastguard Worker this.arrivalLatch = arrival; 153*795d594fSAndroid Build Coastguard Worker this.departureLatch = departure; 154*795d594fSAndroid Build Coastguard Worker } 155*795d594fSAndroid Build Coastguard Worker run()156*795d594fSAndroid Build Coastguard Worker public void run() { 157*795d594fSAndroid Build Coastguard Worker try { 158*795d594fSAndroid Build Coastguard Worker this.arrivalLatch.await(); 159*795d594fSAndroid Build Coastguard Worker maybePrint("REDEFINITION THREAD: redefining something!"); 160*795d594fSAndroid Build Coastguard Worker Redefinition.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES); 161*795d594fSAndroid Build Coastguard Worker maybePrint("REDEFINITION THREAD: redefined something!"); 162*795d594fSAndroid Build Coastguard Worker this.departureLatch.countDown(); 163*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 164*795d594fSAndroid Build Coastguard Worker e.printStackTrace(System.out); 165*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Failed to redefine", e); 166*795d594fSAndroid Build Coastguard Worker } 167*795d594fSAndroid Build Coastguard Worker } 168*795d594fSAndroid Build Coastguard Worker } 169*795d594fSAndroid Build Coastguard Worker maybePrint(String s)170*795d594fSAndroid Build Coastguard Worker private static synchronized void maybePrint(String s) { 171*795d594fSAndroid Build Coastguard Worker if (PRINT) { 172*795d594fSAndroid Build Coastguard Worker System.out.println(s); 173*795d594fSAndroid Build Coastguard Worker } 174*795d594fSAndroid Build Coastguard Worker } 175*795d594fSAndroid Build Coastguard Worker 176*795d594fSAndroid Build Coastguard Worker private static class TestThread extends Thread { 177*795d594fSAndroid Build Coastguard Worker private Transform t; 178*795d594fSAndroid Build Coastguard Worker private TestWatcher w; 179*795d594fSAndroid Build Coastguard Worker private Consumer<Consumer<String>> do_nothing; 180*795d594fSAndroid Build Coastguard Worker private Consumer<Consumer<String>> request_redefinition; TestThread(Transform t, TestWatcher w, Consumer<Consumer<String>> do_nothing, Consumer<Consumer<String>> request_redefinition)181*795d594fSAndroid Build Coastguard Worker public TestThread(Transform t, 182*795d594fSAndroid Build Coastguard Worker TestWatcher w, 183*795d594fSAndroid Build Coastguard Worker Consumer<Consumer<String>> do_nothing, 184*795d594fSAndroid Build Coastguard Worker Consumer<Consumer<String>> request_redefinition) { 185*795d594fSAndroid Build Coastguard Worker super(); 186*795d594fSAndroid Build Coastguard Worker this.t = t; 187*795d594fSAndroid Build Coastguard Worker this.w = w; 188*795d594fSAndroid Build Coastguard Worker this.do_nothing = do_nothing; 189*795d594fSAndroid Build Coastguard Worker this.request_redefinition = request_redefinition; 190*795d594fSAndroid Build Coastguard Worker } 191*795d594fSAndroid Build Coastguard Worker run()192*795d594fSAndroid Build Coastguard Worker public void run() { 193*795d594fSAndroid Build Coastguard Worker w.clear(); 194*795d594fSAndroid Build Coastguard Worker t.sayHi(do_nothing, w); 195*795d594fSAndroid Build Coastguard Worker t.sayHi(request_redefinition, w); 196*795d594fSAndroid Build Coastguard Worker t.sayHi(do_nothing, w); 197*795d594fSAndroid Build Coastguard Worker } 198*795d594fSAndroid Build Coastguard Worker } 199*795d594fSAndroid Build Coastguard Worker ensureJitCompiled(Class c, String name)200*795d594fSAndroid Build Coastguard Worker private static native void ensureJitCompiled(Class c, String name); 201*795d594fSAndroid Build Coastguard Worker } 202