1 /* 2 * Copyright (C) 2017 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.util.Arrays; 18 import java.lang.reflect.Executable; 19 import java.lang.reflect.Method; 20 import java.util.Base64; 21 import art.Breakpoint; 22 import art.Redefinition; 23 24 public class Main { 25 static class Transform { sayHi()26 public void sayHi() { 27 System.out.println("Hello"); 28 } 29 } 30 31 /** 32 * base64 encoded class/dex file for 33 * class Transform { 34 * public void sayHi() { 35 * System.out.println("Goodbye"); 36 * } 37 * } 38 */ 39 private static final byte[] DEX_BYTES = Base64.getDecoder().decode( 40 "ZGV4CjAzNQA7jFommHUzfbuvjq/I2cDcwdjqQk6KPfqYAwAAcAAAAHhWNBIAAAAAAAAAANQCAAAU" + 41 "AAAAcAAAAAkAAADAAAAAAgAAAOQAAAABAAAA/AAAAAQAAAAEAQAAAQAAACQBAABUAgAARAEAAJ4B" + 42 "AACmAQAArwEAAMEBAADJAQAA7QEAAA0CAAAkAgAAOAIAAEwCAABgAgAAawIAAHYCAAB5AgAAfQIA" + 43 "AIoCAACQAgAAlQIAAJ4CAAClAgAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAMAAAA" + 44 "DAAAAAgAAAAAAAAADQAAAAgAAACYAQAABwAEABAAAAAAAAAAAAAAAAAAAAASAAAABAABABEAAAAF" + 45 "AAAAAAAAAAAAAAAAAAAABQAAAAAAAAAKAAAAiAEAAMYCAAAAAAAAAgAAALcCAAC9AgAAAQABAAEA" + 46 "AACsAgAABAAAAHAQAwAAAA4AAwABAAIAAACxAgAACAAAAGIAAAAaAQEAbiACABAADgBEAQAAAAAA" + 47 "AAAAAAAAAAAAAQAAAAYABjxpbml0PgAHR29vZGJ5ZQAQTE1haW4kVHJhbnNmb3JtOwAGTE1haW47" + 48 "ACJMZGFsdmlrL2Fubm90YXRpb24vRW5jbG9zaW5nQ2xhc3M7AB5MZGFsdmlrL2Fubm90YXRpb24v" + 49 "SW5uZXJDbGFzczsAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwASTGphdmEvbGFuZy9PYmplY3Q7ABJM" + 50 "amF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xhbmcvU3lzdGVtOwAJTWFpbi5qYXZhAAlUcmFuc2Zv" + 51 "cm0AAVYAAlZMAAthY2Nlc3NGbGFncwAEbmFtZQADb3V0AAdwcmludGxuAAVzYXlIaQAFdmFsdWUA" + 52 "EgAHDgAUAAcOeAACAgETGAECAwIOBAgPFwsAAAEBAICABNACAQHoAhAAAAAAAAAAAQAAAAAAAAAB" + 53 "AAAAFAAAAHAAAAACAAAACQAAAMAAAAADAAAAAgAAAOQAAAAEAAAAAQAAAPwAAAAFAAAABAAAAAQB" + 54 "AAAGAAAAAQAAACQBAAADEAAAAQAAAEQBAAABIAAAAgAAAFABAAAGIAAAAQAAAIgBAAABEAAAAQAA" + 55 "AJgBAAACIAAAFAAAAJ4BAAADIAAAAgAAAKwCAAAEIAAAAgAAALcCAAAAIAAAAQAAAMYCAAAAEAAA" + 56 "AQAAANQCAAA="); 57 notifyBreakpointReached(Thread thr, Executable e, long loc)58 public static void notifyBreakpointReached(Thread thr, Executable e, long loc) { 59 System.out.println( 60 "\tBreakpoint reached: " + e + " @ line=" + Breakpoint.locationToLine(e, loc)); 61 } 62 check(boolean b, String msg)63 public static void check(boolean b, String msg) { 64 if (!b) { 65 throw new Error("FAILED: " + msg); 66 } 67 } main(String[] args)68 public static void main(String[] args) throws Exception { 69 System.loadLibrary(args[0]); 70 // Set up breakpoints 71 Breakpoint.stopBreakpointWatch(Thread.currentThread()); 72 Breakpoint.startBreakpointWatch( 73 Main.class, 74 Main.class.getDeclaredMethod( 75 "notifyBreakpointReached", Thread.class, Executable.class, Long.TYPE), 76 Thread.currentThread()); 77 78 Method targetMethod = Transform.class.getDeclaredMethod("sayHi"); 79 Transform t = new Transform(); 80 check(isInterpretOnly() || !isMethodDeoptimized(targetMethod), 81 "method should not be deoptimized"); 82 t.sayHi(); 83 84 // Set a breakpoint at the start of the function. 85 Breakpoint.setBreakpoint(targetMethod, 0); 86 check(isInterpretOnly() || isMethodDeoptimized(targetMethod), 87 "method should be deoptimized"); 88 t.sayHi(); 89 90 System.out.println("Redefining transform!"); 91 Redefinition.doCommonClassRedefinition(Transform.class, new byte[0], DEX_BYTES); 92 check(isInterpretOnly() || !isMethodDeoptimized(targetMethod), 93 "method should not be deoptimized"); 94 t.sayHi(); 95 96 Breakpoint.setBreakpoint(targetMethod, 0); 97 check(isInterpretOnly() || isMethodDeoptimized(targetMethod), 98 "method should be deoptimized"); 99 t.sayHi(); 100 } 101 isMethodDeoptimized(Method m)102 static native boolean isMethodDeoptimized(Method m); isInterpretOnly()103 static native boolean isInterpretOnly(); 104 } 105