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 package art; 18 19 import java.lang.reflect.Method; 20 import java.util.HashMap; 21 22 public class Test986 { 23 private static final HashMap<Method, String> SymbolMap = new HashMap<>(); 24 25 // A class with a native method we can play with. 26 static class Transform { sayHi()27 private static native void sayHi(); sayHi2()28 private static native void sayHi2(); 29 } 30 run()31 public static void run() throws Exception { 32 setupNativeBindNotify(); 33 setNativeBindNotify(true); 34 doTest(); 35 } 36 setNativeTransform(Method method, String dest)37 private static void setNativeTransform(Method method, String dest) { 38 SymbolMap.put(method, dest); 39 } 40 removeNativeTransform(Method method)41 private static void removeNativeTransform(Method method) { 42 SymbolMap.remove(method); 43 } 44 45 /** 46 * Notifies java that a native method bind has occurred and requests the new symbol to bind to. 47 */ doNativeMethodBind(Method method, String nativeSym)48 public static String doNativeMethodBind(Method method, String nativeSym) { 49 // Disable native bind notify for now to avoid infinite loops. 50 setNativeBindNotify(false); 51 String transSym = SymbolMap.getOrDefault(method, nativeSym); 52 System.out.println(method + " = " + nativeSym + " -> " + transSym); 53 setNativeBindNotify(true); 54 return transSym; 55 } 56 doTest()57 public static void doTest() throws Exception { 58 Method say_hi_method = Transform.class.getDeclaredMethod("sayHi"); 59 60 // Test we will bind fine if we make no changes. 61 Transform.sayHi2(); 62 63 // Test we can get in the middle of autobind 64 setNativeTransform(say_hi_method, "NoReallySayGoodbye"); 65 Transform.sayHi(); 66 67 // Test we can get in between manual bind. 68 setNativeTransform(say_hi_method, "Java_art_Test986_00024Transform_sayHi2"); 69 rebindTransformClass(); 70 Transform.sayHi(); 71 72 // Test we can get rid of transform 73 removeNativeTransform(say_hi_method); 74 rebindTransformClass(); 75 Transform.sayHi(); 76 } 77 78 // Functions called from native code. doSayHi()79 public static void doSayHi() { 80 System.out.println("Hello"); 81 } 82 doSayHi2()83 public static void doSayHi2() { 84 System.out.println("Hello - 2"); 85 } 86 doSayBye()87 public static void doSayBye() { 88 System.out.println("Bye"); 89 } 90 setNativeBindNotify(boolean enable)91 private static native void setNativeBindNotify(boolean enable); setupNativeBindNotify()92 private static native void setupNativeBindNotify(); rebindTransformClass()93 private static void rebindTransformClass() { 94 rebindTransformClass(Transform.class); 95 } rebindTransformClass(Class<?> trans)96 private static native void rebindTransformClass(Class<?> trans); 97 } 98