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 package art; 18 19 import java.util.Base64; 20 import java.util.concurrent.Semaphore; 21 22 public class Test951 { 23 24 static class Transform { sayHi(Runnable r)25 public void sayHi(Runnable r) { 26 System.out.println("hello"); 27 r.run(); 28 System.out.println("goodbye"); 29 } 30 } 31 32 // static class Transform { 33 // public void sayHi(Runnable r) { 34 // System.out.println("Hello - Transformed"); 35 // r.run(); 36 // System.out.println("Goodbye - Transformed"); 37 // } 38 // } 39 private static final byte[] CLASS_BYTES = Base64.getDecoder().decode( 40 "yv66vgAAADQAKAoACAARCQASABMIABQKABUAFgsAFwAYCAAZBwAbBwAeAQAGPGluaXQ+AQADKClW" + 41 "AQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEABXNheUhpAQAXKExqYXZhL2xhbmcvUnVubmFibGU7" + 42 "KVYBAApTb3VyY2VGaWxlAQAMVGVzdDk1MS5qYXZhDAAJAAoHAB8MACAAIQEAE0hlbGxvIC0gVHJh" + 43 "bnNmb3JtZWQHACIMACMAJAcAJQwAJgAKAQAVR29vZGJ5ZSAtIFRyYW5zZm9ybWVkBwAnAQAVYXJ0" + 44 "L1Rlc3Q5NTEkVHJhbnNmb3JtAQAJVHJhbnNmb3JtAQAMSW5uZXJDbGFzc2VzAQAQamF2YS9sYW5n" + 45 "L09iamVjdAEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsB" + 46 "ABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgEA" + 47 "EmphdmEvbGFuZy9SdW5uYWJsZQEAA3J1bgEAC2FydC9UZXN0OTUxACAABwAIAAAAAAACAAAACQAK" + 48 "AAEACwAAAB0AAQABAAAABSq3AAGxAAAAAQAMAAAABgABAAAABQABAA0ADgABAAsAAAA7AAIAAgAA" + 49 "ABeyAAISA7YABCu5AAUBALIAAhIGtgAEsQAAAAEADAAAABIABAAAAAcACAAIAA4ACQAWAAoAAgAP" + 50 "AAAAAgAQAB0AAAAKAAEABwAaABwACA=="); 51 private static final byte[] DEX_BYTES = Base64.getDecoder().decode( 52 "ZGV4CjAzNQBom/JeAAAAAAAAAAAAAAAAAAAAAAAAAAA8BAAAcAAAAHhWNBIAAAAAAAAAAHgDAAAX" + 53 "AAAAcAAAAAoAAADMAAAAAwAAAPQAAAABAAAAGAEAAAUAAAAgAQAAAQAAAEgBAADUAgAAaAEAAGgB" + 54 "AABwAQAAhwEAAJwBAAC1AQAAxAEAAOgBAAAIAgAAHwIAADMCAABJAgAAXQIAAHECAAB/AgAAigIA" + 55 "AI0CAACRAgAAngIAAKQCAACpAgAAsgIAALcCAAC+AgAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAA" + 56 "CQAAAAoAAAALAAAADgAAAA4AAAAJAAAAAAAAAA8AAAAJAAAAyAIAAA8AAAAJAAAA0AIAAAgABAAS" + 57 "AAAAAAAAAAAAAAAAAAEAFQAAAAQAAgATAAAABQAAAAAAAAAGAAAAFAAAAAAAAAAAAAAABQAAAAAA" + 58 "AAAMAAAAaAMAADwDAAAAAAAABjxpbml0PgAVR29vZGJ5ZSAtIFRyYW5zZm9ybWVkABNIZWxsbyAt" + 59 "IFRyYW5zZm9ybWVkABdMYXJ0L1Rlc3Q5NTEkVHJhbnNmb3JtOwANTGFydC9UZXN0OTUxOwAiTGRh" + 60 "bHZpay9hbm5vdGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0aW9uL0lubmVy" + 61 "Q2xhc3M7ABVMamF2YS9pby9QcmludFN0cmVhbTsAEkxqYXZhL2xhbmcvT2JqZWN0OwAUTGphdmEv" + 62 "bGFuZy9SdW5uYWJsZTsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AAxU" + 63 "ZXN0OTUxLmphdmEACVRyYW5zZm9ybQABVgACVkwAC2FjY2Vzc0ZsYWdzAARuYW1lAANvdXQAB3By" + 64 "aW50bG4AA3J1bgAFc2F5SGkABXZhbHVlAAAAAAEAAAAGAAAAAQAAAAcAAAAFAAcOAAcBAAcOAQgP" + 65 "AQMPAQgPAAEAAQABAAAA2AIAAAQAAABwEAMAAAAOAAQAAgACAAAA3QIAABQAAABiAAAAGwECAAAA" + 66 "biACABAAchAEAAMAYgAAABsBAQAAAG4gAgAQAA4AAAABAQCAgATsBQEBhAYAAAICARYYAQIDAhAE" + 67 "CBEXDQACAAAATAMAAFIDAABcAwAAAAAAAAAAAAAAAAAAEAAAAAAAAAABAAAAAAAAAAEAAAAXAAAA" + 68 "cAAAAAIAAAAKAAAAzAAAAAMAAAADAAAA9AAAAAQAAAABAAAAGAEAAAUAAAAFAAAAIAEAAAYAAAAB" + 69 "AAAASAEAAAIgAAAXAAAAaAEAAAEQAAACAAAAyAIAAAMgAAACAAAA2AIAAAEgAAACAAAA7AIAAAAg" + 70 "AAABAAAAPAMAAAQgAAACAAAATAMAAAMQAAABAAAAXAMAAAYgAAABAAAAaAMAAAAQAAABAAAAeAMA" + 71 "AA=="); 72 run()73 public static void run() { 74 // Semaphores to let each thread know where the other is. We could use barriers but semaphores 75 // mean we don't need to have the worker thread be waiting around. 76 final Semaphore sem_redefine_start = new Semaphore(0); 77 final Semaphore sem_redefine_end = new Semaphore(0); 78 // Create a thread to do the actual redefinition. We will just communicate through an 79 // atomic-integer. 80 new Thread(() -> { 81 try { 82 // Wait for the other thread to ask for redefinition. 83 sem_redefine_start.acquire(); 84 // Do the redefinition. 85 Redefinition.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES); 86 // Allow the other thread to wake up if it is waiting. 87 sem_redefine_end.release(); 88 } catch (InterruptedException e) { 89 throw new Error("unable to do redefinition", e); 90 } 91 }).start(); 92 93 Transform t = new Transform(); 94 t.sayHi(() -> { System.out.println("Not doing anything here"); }); 95 t.sayHi(() -> { 96 try { 97 System.out.println("transforming calling function"); 98 // Wake up the waiting thread. 99 sem_redefine_start.release(); 100 // Wait for the other thread to finish with redefinition. 101 sem_redefine_end.acquire(); 102 } catch (InterruptedException e) { 103 throw new Error("unable to do redefinition", e); 104 } 105 }); 106 t.sayHi(() -> { System.out.println("Not doing anything here"); }); 107 } 108 } 109