• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 import art.Redefinition;
19 
20 import java.util.function.Consumer;
21 import java.lang.reflect.Method;
22 import java.util.Base64;
23 
24 public class Main {
25 
26     // import java.util.function.Consumer;
27     //
28     // class Transform {
29     //     private void Start(Consumer<String> reporter) {
30     //         reporter.accept("Hello - private - Transformed");
31     //     }
32     //
33     //     private void Finish(Consumer<String> reporter) {
34     //        reporter.accept("Goodbye - private - Transformed");
35     //     }
36     //
37     //     public void sayHi(Runnable r, Consumer<String> reporter) {
38     //         reporter.accept("pre Start private method call - Transformed");
39     //         Start(reporter);
40     //         reporter.accept("post Start private method call - Transformed");
41     //         r.run();
42     //         reporter.accept("pre Finish private method call - Transformed");
43     //         Finish(reporter);
44     //         reporter.accept("post Finish private method call - Transformed");
45     //     }
46     // }
47     private static final byte[] CLASS_BYTES = Base64.getDecoder().decode(
48             "yv66vgAAADQAMAoADQAcCAAdCwAeAB8IACAIACEKAAwAIggAIwsAJAAlCAAmCgAMACcIACgHACkH" +
49             "ACoBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAFU3RhcnQBACAoTGph" +
50             "dmEvdXRpbC9mdW5jdGlvbi9Db25zdW1lcjspVgEACVNpZ25hdHVyZQEANChMamF2YS91dGlsL2Z1" +
51             "bmN0aW9uL0NvbnN1bWVyPExqYXZhL2xhbmcvU3RyaW5nOz47KVYBAAZGaW5pc2gBAAVzYXlIaQEA" +
52             "NChMamF2YS9sYW5nL1J1bm5hYmxlO0xqYXZhL3V0aWwvZnVuY3Rpb24vQ29uc3VtZXI7KVYBAEgo" +
53             "TGphdmEvbGFuZy9SdW5uYWJsZTtMamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyPExqYXZhL2xh" +
54             "bmcvU3RyaW5nOz47KVYBAApTb3VyY2VGaWxlAQAOVHJhbnNmb3JtLmphdmEMAA4ADwEAHUhlbGxv" +
55             "IC0gcHJpdmF0ZSAtIFRyYW5zZm9ybWVkBwArDAAsAC0BAB9Hb29kYnllIC0gcHJpdmF0ZSAtIFRy" +
56             "YW5zZm9ybWVkAQArcHJlIFN0YXJ0IHByaXZhdGUgbWV0aG9kIGNhbGwgLSBUcmFuc2Zvcm1lZAwA" +
57             "EgATAQAscG9zdCBTdGFydCBwcml2YXRlIG1ldGhvZCBjYWxsIC0gVHJhbnNmb3JtZWQHAC4MAC8A" +
58             "DwEALHByZSBGaW5pc2ggcHJpdmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkDAAWABMBAC1w" +
59             "b3N0IEZpbmlzaCBwcml2YXRlIG1ldGhvZCBjYWxsIC0gVHJhbnNmb3JtZWQBAAlUcmFuc2Zvcm0B" +
60             "ABBqYXZhL2xhbmcvT2JqZWN0AQAbamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyAQAGYWNjZXB0" +
61             "AQAVKExqYXZhL2xhbmcvT2JqZWN0OylWAQASamF2YS9sYW5nL1J1bm5hYmxlAQADcnVuACAADAAN" +
62             "AAAAAAAEAAAADgAPAAEAEAAAAB0AAQABAAAABSq3AAGxAAAAAQARAAAABgABAAAAEwACABIAEwAC" +
63             "ABAAAAAlAAIAAgAAAAkrEgK5AAMCALEAAAABABEAAAAKAAIAAAAVAAgAFgAUAAAAAgAVAAIAFgAT" +
64             "AAIAEAAAACUAAgACAAAACSsSBLkAAwIAsQAAAAEAEQAAAAoAAgAAABkACAAaABQAAAACABUAAQAX" +
65             "ABgAAgAQAAAAZQACAAMAAAAxLBIFuQADAgAqLLcABiwSB7kAAwIAK7kACAEALBIJuQADAgAqLLcA" +
66             "CiwSC7kAAwIAsQAAAAEAEQAAACIACAAAAB0ACAAeAA0AHwAVACAAGwAhACMAIgAoACMAMAAkABQA" +
67             "AAACABkAAQAaAAAAAgAb");
68     private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
69             "ZGV4CjAzNQBc8wr9PcHqnOR61m+0kimXTSddVMToJPuYBQAAcAAAAHhWNBIAAAAAAAAAAOAEAAAc" +
70             "AAAAcAAAAAYAAADgAAAABAAAAPgAAAAAAAAAAAAAAAcAAAAoAQAAAQAAAGABAAAYBAAAgAEAAHoC" +
71             "AAB9AgAAgAIAAIgCAACOAgAAlgIAALcCAADWAgAA4wIAAAIDAAAWAwAALAMAAEADAABeAwAAfQMA" +
72             "AIQDAACUAwAAlwMAAJsDAACgAwAAqAMAALwDAADrAwAAGQQAAEcEAAB0BAAAeQQAAIAEAAAHAAAA" +
73             "CAAAAAkAAAAKAAAADQAAABAAAAAQAAAABQAAAAAAAAARAAAABQAAAGQCAAASAAAABQAAAGwCAAAR" +
74             "AAAABQAAAHQCAAAAAAAAAgAAAAAAAwAEAAAAAAADAA4AAAAAAAIAGgAAAAIAAAACAAAAAwAAABkA" +
75             "AAAEAAEAEwAAAAAAAAAAAAAAAgAAAAAAAAAPAAAAPAIAAMoEAAAAAAAAAQAAAKgEAAABAAAAuAQA" +
76             "AAEAAQABAAAAhwQAAAQAAABwEAQAAAAOAAMAAgACAAAAjAQAAAcAAAAbAAUAAAByIAYAAgAOAAAA" +
77             "AwACAAIAAACTBAAABwAAABsABgAAAHIgBgACAA4AAAAEAAMAAgAAAJoEAAAiAAAAGwAYAAAAciAG" +
78             "AAMAcCACADEAGwAWAAAAciAGAAMAchAFAAIAGwAXAAAAciAGAAMAcCABADEAGwAVAAAAciAGAAMA" +
79             "DgAAAAAAAAAAAAMAAAAAAAAAAQAAAIABAAACAAAAgAEAAAMAAACIAQAAAQAAAAIAAAACAAAAAwAE" +
80             "AAEAAAAEAAEoAAE8AAY8aW5pdD4ABD47KVYABkZpbmlzaAAfR29vZGJ5ZSAtIHByaXZhdGUgLSBU" +
81             "cmFuc2Zvcm1lZAAdSGVsbG8gLSBwcml2YXRlIC0gVHJhbnNmb3JtZWQAC0xUcmFuc2Zvcm07AB1M" +
82             "ZGFsdmlrL2Fubm90YXRpb24vU2lnbmF0dXJlOwASTGphdmEvbGFuZy9PYmplY3Q7ABRMamF2YS9s" +
83             "YW5nL1J1bm5hYmxlOwASTGphdmEvbGFuZy9TdHJpbmc7ABxMamF2YS91dGlsL2Z1bmN0aW9uL0Nv" +
84             "bnN1bWVyAB1MamF2YS91dGlsL2Z1bmN0aW9uL0NvbnN1bWVyOwAFU3RhcnQADlRyYW5zZm9ybS5q" +
85             "YXZhAAFWAAJWTAADVkxMAAZhY2NlcHQAEmVtaXR0ZXI6IGphY2stNC4xOQAtcG9zdCBGaW5pc2gg" +
86             "cHJpdmF0ZSBtZXRob2QgY2FsbCAtIFRyYW5zZm9ybWVkACxwb3N0IFN0YXJ0IHByaXZhdGUgbWV0" +
87             "aG9kIGNhbGwgLSBUcmFuc2Zvcm1lZAAscHJlIEZpbmlzaCBwcml2YXRlIG1ldGhvZCBjYWxsIC0g" +
88             "VHJhbnNmb3JtZWQAK3ByZSBTdGFydCBwcml2YXRlIG1ldGhvZCBjYWxsIC0gVHJhbnNmb3JtZWQA" +
89             "A3J1bgAFc2F5SGkABXZhbHVlABMABw4AGQEABw5pABUBAAcOaQAdAgAABw5pPGk8aTxpAAIBARsc" +
90             "BRcAFwwXARcLFwMCAQEbHAYXABcKFwwXARcLFwMAAAMBAICABJADAQKoAwECyAMDAegDDwAAAAAA" +
91             "AAABAAAAAAAAAAEAAAAcAAAAcAAAAAIAAAAGAAAA4AAAAAMAAAAEAAAA+AAAAAUAAAAHAAAAKAEA" +
92             "AAYAAAABAAAAYAEAAAMQAAACAAAAgAEAAAEgAAAEAAAAkAEAAAYgAAABAAAAPAIAAAEQAAADAAAA" +
93             "ZAIAAAIgAAAcAAAAegIAAAMgAAAEAAAAhwQAAAQgAAACAAAAqAQAAAAgAAABAAAAygQAAAAQAAAB" +
94             "AAAA4AQAAA==");
95 
96     // A class that we can use to keep track of the output of this test.
97     private static class TestWatcher implements Consumer<String> {
98         private StringBuilder sb;
TestWatcher()99         public TestWatcher() {
100             sb = new StringBuilder();
101         }
102 
103         @Override
accept(String s)104         public void accept(String s) {
105             sb.append(s);
106             sb.append('\n');
107         }
108 
getOutput()109         public String getOutput() {
110             return sb.toString();
111         }
112 
clear()113         public void clear() {
114             sb = new StringBuilder();
115         }
116     }
117 
main(String[] args)118     public static void main(String[] args) {
119         doTest(new Transform(), new TestWatcher());
120     }
121 
122     private static boolean interpreting = true;
123     private static boolean retry = false;
124 
doTest(Transform t, TestWatcher w)125     public static void doTest(Transform t, TestWatcher w) {
126         // Get the methods that need to be optimized.
127         Method say_hi_method;
128         // Figure out if we can even JIT at all.
129         final boolean has_jit = hasJit();
130         try {
131             say_hi_method = Transform.class.getDeclaredMethod(
132                     "sayHi", Runnable.class, Consumer.class);
133         } catch (Exception e) {
134             System.out.println("Unable to find methods!");
135             e.printStackTrace(System.out);
136             return;
137         }
138         // Makes sure the stack is the way we want it for the test and does the redefinition.
139         // It will set the retry boolean to true if the stack does not have a JIT-compiled
140         // sayHi entry. This can only happen if the method gets GC'd.
141         Runnable do_redefinition = () -> {
142             if (has_jit && Main.isInterpretedFunction(say_hi_method, true)) {
143                 // Try again. We are not running the right jitted methods/cannot redefine them now.
144                 retry = true;
145             } else {
146                 // Actually do the redefinition. The stack looks good.
147                 retry = false;
148                 w.accept("transforming calling function");
149                 Redefinition.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES);
150             }
151         };
152         // This just prints something out to show we are running the Runnable.
153         Runnable say_nothing = () -> { w.accept("Not doing anything here"); };
154         do {
155             // Run ensureJitCompiled here since it might get GCd
156             ensureJitCompiled(Transform.class, "sayHi");
157             // Clear output.
158             w.clear();
159             // Try and redefine.
160             t.sayHi(say_nothing, w);
161             t.sayHi(do_redefinition, w);
162             t.sayHi(say_nothing, w);
163         } while (retry);
164         // Print output of last run.
165         System.out.print(w.getOutput());
166     }
167 
hasJit()168     private static native boolean hasJit();
169 
isInterpretedFunction(Method m, boolean require_deoptimizable)170     private static native boolean isInterpretedFunction(Method m, boolean require_deoptimizable);
171 
ensureJitCompiled(Class c, String name)172     private static native void ensureJitCompiled(Class c, String name);
173 }
174