blob: 40972db64392263d78b2dc49e9e4b7ec1ab00205 [file] [log] [blame]
Alex Light270db1c2019-12-03 12:20:01 +00001/*
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
17package art;
18
19import dalvik.system.InMemoryDexClassLoader;
20import java.nio.ByteBuffer;
21import java.util.ArrayList;
22import java.util.Base64;
23import java.util.concurrent.CountDownLatch;
24import java.util.function.Supplier;
25
26public class Test2001 {
27 private static final int NUM_THREADS = 20;
Alex Light93be70e2020-01-07 17:05:42 +000028 // Don't perform more than this many repeats per thread to prevent OOMEs
29 private static final int TASK_COUNT_LIMIT = 1000;
Alex Light270db1c2019-12-03 12:20:01 +000030
31 public static class Transform {
32 public String greetingEnglish;
33
34 public Transform() {
35 this.greetingEnglish = "Hello";
36 }
37
38 public String sayHi() {
39 return greetingEnglish + " from " + Thread.currentThread().getName();
40 }
41 }
42
43 /**
44 * base64 encoded class/dex file for
45 * public static class Transform {
46 * public String greetingEnglish;
47 * public String greetingFrench;
48 * public String greetingDanish;
49 * public String greetingJapanese;
50 *
51 * public Transform() {
52 * this.greetingEnglish = "Hello World";
53 * this.greetingFrench = "Bonjour le Monde";
54 * this.greetingDanish = "Hej Verden";
55 * this.greetingJapanese = "こんにちは世界";
56 * }
57 * public String sayHi() {
58 * return sayHiEnglish() + ", " + sayHiFrench() + ", " + sayHiDanish() + ", " + sayHiJapanese() + " from " + Thread.currentThread().getName();
59 * }
60 * public String sayHiEnglish() {
61 * return greetingEnglish;
62 * }
63 * public String sayHiDanish() {
64 * return greetingDanish;
65 * }
66 * public String sayHiJapanese() {
67 * return greetingJapanese;
68 * }
69 * public String sayHiFrench() {
70 * return greetingFrench;
71 * }
72 * }
73 */
74 private static final byte[] DEX_BYTES =
75 Base64.getDecoder()
76 .decode(
77 "ZGV4CjAzNQCnKPY06VRa4aM/zFW0MYLmRxT/NtXxD/H4BgAAcAAAAHhWNBIAAAAAAAAAADQGAAAl"
78 + "AAAAcAAAAAkAAAAEAQAABAAAACgBAAAEAAAAWAEAAAwAAAB4AQAAAQAAANgBAAAABQAA+AEAAEoD"
79 + "AABSAwAAVgMAAF4DAABwAwAAfAMAAIkDAACMAwAAkAMAAKoDAAC6AwAA3gMAAP4DAAASBAAAJgQA"
80 + "AEEEAABVBAAAZAQAAG8EAAByBAAAfwQAAIcEAACWBAAAnwQAAK8EAADABAAA0AQAAOIEAADoBAAA"
81 + "7wQAAPwEAAAKBQAAFwUAACYFAAAwBQAANwUAAMUFAAAIAAAACQAAAAoAAAALAAAADAAAAA0AAAAO"
82 + "AAAADwAAABIAAAAGAAAABQAAAAAAAAAHAAAABgAAAEQDAAAGAAAABwAAAAAAAAASAAAACAAAAAAA"
83 + "AAAAAAUAFwAAAAAABQAYAAAAAAAFABkAAAAAAAUAGgAAAAAAAwACAAAAAAAAABwAAAAAAAAAHQAA"
84 + "AAAAAAAeAAAAAAAAAB8AAAAAAAAAIAAAAAQAAwACAAAABgADAAIAAAAGAAEAFAAAAAYAAAAhAAAA"
85 + "BwACABUAAAAHAAAAFgAAAAAAAAABAAAABAAAAAAAAAAQAAAAJAYAAOsFAAAAAAAABwABAAIAAAAt"
86 + "AwAAQQAAAG4QAwAGAAwAbhAEAAYADAFuEAIABgAMAm4QBQAGAAwDcQAKAAAADARuEAsABAAMBCIF"
87 + "BgBwEAcABQBuIAgABQAaAAEAbiAIAAUAbiAIABUAbiAIAAUAbiAIACUAbiAIAAUAbiAIADUAGgAA"
88 + "AG4gCAAFAG4gCABFAG4QCQAFAAwAEQAAAAIAAQAAAAAAMQMAAAMAAABUEAAAEQAAAAIAAQAAAAAA"
89 + "NQMAAAMAAABUEAEAEQAAAAIAAQAAAAAAOQMAAAMAAABUEAIAEQAAAAIAAQAAAAAAPQMAAAMAAABU"
90 + "EAMAEQAAAAIAAQABAAAAJAMAABQAAABwEAYAAQAaAAUAWxABABoAAwBbEAIAGgAEAFsQAAAaACQA"
91 + "WxADAA4ACwAOPEtLS0sAEgAOABgADgAVAA4AHgAOABsADgAAAAABAAAABQAGIGZyb20gAAIsIAAG"
92 + "PGluaXQ+ABBCb25qb3VyIGxlIE1vbmRlAApIZWogVmVyZGVuAAtIZWxsbyBXb3JsZAABTAACTEwA"
93 + "GExhcnQvVGVzdDIwMDEkVHJhbnNmb3JtOwAOTGFydC9UZXN0MjAwMTsAIkxkYWx2aWsvYW5ub3Rh"
94 + "dGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwASTGph"
95 + "dmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAGUxqYXZhL2xhbmcvU3RyaW5nQnVp"
96 + "bGRlcjsAEkxqYXZhL2xhbmcvVGhyZWFkOwANVGVzdDIwMDEuamF2YQAJVHJhbnNmb3JtAAFWAAth"
97 + "Y2Nlc3NGbGFncwAGYXBwZW5kAA1jdXJyZW50VGhyZWFkAAdnZXROYW1lAA5ncmVldGluZ0Rhbmlz"
98 + "aAAPZ3JlZXRpbmdFbmdsaXNoAA5ncmVldGluZ0ZyZW5jaAAQZ3JlZXRpbmdKYXBhbmVzZQAEbmFt"
99 + "ZQAFc2F5SGkAC3NheUhpRGFuaXNoAAxzYXlIaUVuZ2xpc2gAC3NheUhpRnJlbmNoAA1zYXlIaUph"
100 + "cGFuZXNlAAh0b1N0cmluZwAFdmFsdWUAiwF+fkQ4eyJjb21waWxhdGlvbi1tb2RlIjoiZGVidWci"
101 + "LCJoYXMtY2hlY2tzdW1zIjpmYWxzZSwibWluLWFwaSI6MSwic2hhLTEiOiJmNjJiOGNlNmEwNTkw"
102 + "MDU0ZWYzNGExYWVkZTcwYjQ2NjY4ZThiNDlmIiwidmVyc2lvbiI6IjIuMC4xLWRldiJ9AAfjgZPj"
103 + "gpPjgavjgaHjga/kuJbnlYwAAgIBIhgBAgMCEwQJGxcRAAQBBQABAQEBAQEBAIGABOwFAQH4AwEB"
104 + "jAUBAaQFAQG8BQEB1AUAAAAAAAAAAgAAANwFAADiBQAAGAYAAAAAAAAAAAAAAAAAABAAAAAAAAAA"
105 + "AQAAAAAAAAABAAAAJQAAAHAAAAACAAAACQAAAAQBAAADAAAABAAAACgBAAAEAAAABAAAAFgBAAAF"
106 + "AAAADAAAAHgBAAAGAAAAAQAAANgBAAABIAAABgAAAPgBAAADIAAABgAAACQDAAABEAAAAQAAAEQD"
107 + "AAACIAAAJQAAAEoDAAAEIAAAAgAAANwFAAAAIAAAAQAAAOsFAAADEAAAAgAAABQGAAAGIAAAAQAA"
108 + "ACQGAAAAEAAAAQAAADQGAAA=");
109
110 /*
111 * base64 encoded class/dex file for
112 package art;
113 import java.util.function.Supplier;
114 public class SubTransform extends art.Test2001.Transform implements Supplier<String> {
115 public SubTransform() {
116 super();
117 }
118 public String get() {
119 return "from SUBCLASS: " + super.sayHi();
120 }
121 }
122 */
123 private static final byte[] SUB_DEX_BYTES =
124 Base64.getDecoder()
125 .decode(
126 "ZGV4CjAzNQBawzkIDf9khFw00md41U4vIqRuhqBTjM+0BAAAcAAAAHhWNBIAAAAAAAAAAPwDAAAV"
127 + "AAAAcAAAAAgAAADEAAAABAAAAOQAAAAAAAAAAAAAAAgAAAAUAQAAAQAAAFQBAABAAwAAdAEAAAIC"
128 + "AAAKAgAADgIAABECAAAVAgAAKQIAAEMCAABiAgAAdgIAAIoCAAClAgAAxAIAAOMCAAD2AgAA+QIA"
129 + "AAEDAAASAwAAFwMAAB4DAAAoAwAALwMAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAoAAAANAAAA"
130 + "AgAAAAMAAAAAAAAAAgAAAAQAAAAAAAAAAwAAAAUAAAD8AQAADQAAAAcAAAAAAAAAAAADAAAAAAAA"
131 + "AAAAEAAAAAAAAQAQAAAAAQADAAAAAAABAAEAEQAAAAUAAwAAAAAABQACAA4AAAAFAAEAEgAAAAAA"
132 + "AAABAAAAAQAAAPQBAAAMAAAA7AMAAMsDAAAAAAAAAgABAAEAAADpAQAABQAAAG4QAgABAAwAEQAA"
133 + "AAQAAQACAAAA7QEAABYAAABvEAQAAwAMACIBBQBwEAUAAQAaAg8AbiAGACEAbiAGAAEAbhAHAAEA"
134 + "DAARAAEAAQABAAAA5AEAAAQAAABwEAMAAAAOAAYADjwABAAOAAkADgAAAAABAAAABgAAAAEAAAAE"
135 + "AAY8aW5pdD4AAj47AAFMAAJMTAASTGFydC9TdWJUcmFuc2Zvcm07ABhMYXJ0L1Rlc3QyMDAxJFRy"
136 + "YW5zZm9ybTsAHUxkYWx2aWsvYW5ub3RhdGlvbi9TaWduYXR1cmU7ABJMamF2YS9sYW5nL09iamVj"
137 + "dDsAEkxqYXZhL2xhbmcvU3RyaW5nOwAZTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwAdTGphdmEv"
138 + "dXRpbC9mdW5jdGlvbi9TdXBwbGllcjsAHUxqYXZhL3V0aWwvZnVuY3Rpb24vU3VwcGxpZXI8ABFT"
139 + "dWJUcmFuc2Zvcm0uamF2YQABVgAGYXBwZW5kAA9mcm9tIFNVQkNMQVNTOiAAA2dldAAFc2F5SGkA"
140 + "CHRvU3RyaW5nAAV2YWx1ZQCLAX5+RDh7ImNvbXBpbGF0aW9uLW1vZGUiOiJkZWJ1ZyIsImhhcy1j"
141 + "aGVja3N1bXMiOmZhbHNlLCJtaW4tYXBpIjoxLCJzaGEtMSI6ImY2MmI4Y2U2YTA1OTAwNTRlZjM0"
142 + "YTFhZWRlNzBiNDY2NjhlOGI0OWYiLCJ2ZXJzaW9uIjoiMi4wLjEtZGV2In0AAgIBExwEFwUXCxcI"
143 + "FwEAAAECAIGABMwDAcEg9AIBAZADAAAAAAAAAQAAAL0DAADkAwAAAAAAAAAAAAAAAAAADwAAAAAA"
144 + "AAABAAAAAAAAAAEAAAAVAAAAcAAAAAIAAAAIAAAAxAAAAAMAAAAEAAAA5AAAAAUAAAAIAAAAFAEA"
145 + "AAYAAAABAAAAVAEAAAEgAAADAAAAdAEAAAMgAAADAAAA5AEAAAEQAAACAAAA9AEAAAIgAAAVAAAA"
146 + "AgIAAAQgAAABAAAAvQMAAAAgAAABAAAAywMAAAMQAAACAAAA4AMAAAYgAAABAAAA7AMAAAAQAAAB"
147 + "AAAA/AMAAA==");
148
149 public static void run() throws Exception {
150 Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE);
151 doTest();
152 }
153
154 public static Supplier<String> mkTransform() {
155 try {
156 return (Supplier<String>)
157 (new InMemoryDexClassLoader(
158 ByteBuffer.wrap(SUB_DEX_BYTES), Test2001.class.getClassLoader())
159 .loadClass("art.SubTransform")
160 .newInstance());
161 } catch (Exception e) {
162 return () -> {
163 return e.toString();
164 };
165 }
166 }
167
168 public static final class MyThread extends Thread {
169 public MyThread(CountDownLatch delay, int id) {
170 super("Thread: " + id);
171 this.thr_id = id;
Alex Light93be70e2020-01-07 17:05:42 +0000172 this.results = new ArrayList<>(TASK_COUNT_LIMIT);
Alex Light270db1c2019-12-03 12:20:01 +0000173 this.finish = false;
174 this.delay = delay;
175 }
176
177 public void run() {
178 delay.countDown();
Alex Light93be70e2020-01-07 17:05:42 +0000179 while (!finish && results.size() < TASK_COUNT_LIMIT) {
Alex Light270db1c2019-12-03 12:20:01 +0000180 Supplier<String> t = mkTransform();
181 results.add(t.get());
182 }
183 }
184
185 public void finish() throws Exception {
186 finish = true;
187 this.join();
188 }
189
190 public void Check() throws Exception {
191 for (String s : results) {
192 if (!s.equals("from SUBCLASS: Hello from " + getName())
193 && !s.equals("from SUBCLASS: Hello, null, null, null from " + getName())
194 && !s.equals(
195 "from SUBCLASS: Hello World, Bonjour le Monde, Hej Verden, こんにちは世界 from "
196 + getName())) {
197 System.out.println("FAIL " + thr_id + ": Unexpected result: " + s);
198 }
199 }
200 }
201
202 public ArrayList<String> results;
203 public volatile boolean finish;
204 public int thr_id;
205 public CountDownLatch delay;
206 }
207
208 public static MyThread[] startThreads(int num_threads) throws Exception {
209 CountDownLatch cdl = new CountDownLatch(num_threads);
210 MyThread[] res = new MyThread[num_threads];
211 for (int i = 0; i < num_threads; i++) {
212 res[i] = new MyThread(cdl, i);
213 res[i].start();
214 }
215 cdl.await();
216 return res;
217 }
218
219 public static void finishThreads(MyThread[] thrs) throws Exception {
220 for (MyThread t : thrs) {
221 t.finish();
222 }
223 for (MyThread t : thrs) {
224 t.Check();
225 }
226 }
227
228 public static void doTest() throws Exception {
229 MyThread[] threads = startThreads(NUM_THREADS);
230 Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES);
231 finishThreads(threads);
232 }
233}