1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 package android.jvmti.cts; 15 16 import static org.junit.Assert.assertEquals; 17 import static org.junit.Assert.assertArrayEquals; 18 import static org.junit.Assert.assertTrue; 19 20 import dalvik.system.InMemoryDexClassLoader; 21 22 import java.lang.ref.WeakReference; 23 import java.nio.ByteBuffer; 24 import java.util.Arrays; 25 import java.util.ArrayList; 26 import java.util.Base64; 27 import java.util.Collections; 28 import java.util.LinkedList; 29 import java.util.List; 30 31 import org.junit.Assert; 32 import org.junit.After; 33 import org.junit.Before; 34 import org.junit.BeforeClass; 35 import org.junit.Test; 36 37 import art.Main; 38 39 /** 40 * Check redefineClasses-related functionality. 41 */ 42 public class JvmtiRedefineClassesTest extends JvmtiTestBase { 43 44 @Before setUp()45 public void setUp() throws Exception { 46 // make sure everything is cleared. 47 setTransformationEvent(false); 48 setPopTransformations(true); 49 clearTransformations(); 50 // Make sure Transform.class is in the initial state. 51 checkRedefinition(INITIAL_TRANSFORM); 52 } 53 54 static class RedefineError { 55 public int expectedError; 56 public Class<?> target; 57 public byte[] dexData; 58 RedefineError(int err, Class<?> target, String base64string)59 public RedefineError(int err, Class<?> target, String base64string) { 60 this(err, target, Base64.getDecoder().decode(base64string)); 61 } 62 RedefineError(int err, Class<?> klass, byte[] dex)63 public RedefineError(int err, Class<?> klass, byte[] dex) { 64 this.expectedError = err; 65 this.target = klass; 66 this.dexData = dex; 67 } 68 } 69 70 // Just an interface. 71 interface Consumer<T> { accept(T data)72 public void accept(T data); 73 } 74 75 static class StringCollector implements Consumer<String> { 76 public ArrayList<String> reports = new ArrayList<>(); 77 accept(String data)78 public void accept(String data) { 79 reports.add(data); 80 } 81 } 82 83 /** 84 * Try to redefine a class and assert that the redefinition matches whats expected. 85 */ checkRedefinition(RedefineError err)86 private static void checkRedefinition(RedefineError err) { 87 assertEquals(err.expectedError, redefineClass(err.target, err.dexData)); 88 } 89 90 // This is a class that we will transform for tests. 91 // NB This has the actual name Landroid/jvmti/cts/JvmtiRedefineClassesTest$Transform; 92 static class Transform { 93 // NB This field has type Landroid/jvmti/cts/JvmtiRedefineClassesTest$Consumer; 94 private Consumer<String> reporter; 95 Transform(Consumer<String> reporter)96 public Transform(Consumer<String> reporter) { 97 this.reporter = reporter; 98 } 99 Start()100 private void Start() { 101 reporter.accept("hello - private"); 102 } 103 Finish()104 private void Finish() { 105 reporter.accept("goodbye - private"); 106 } 107 sayHi(Runnable r)108 public void sayHi(Runnable r) { 109 reporter.accept("Pre Start private method call"); 110 Start(); 111 reporter.accept("Post Start private method call"); 112 r.run(); 113 reporter.accept("Pre Finish private method call"); 114 Finish(); 115 reporter.accept("Post Finish private method call"); 116 } 117 } 118 119 /** 120 * Base64 encoded dex file for the initial version of Transform class. 121 */ 122 private static final RedefineError INITIAL_TRANSFORM = new RedefineError( 123 JvmtiErrors.NONE, Transform.class, 124 "ZGV4CjAzNQA+L+iHAAAAAAAAAAAAAAAAAAAAAAAAAACgBgAAcAAAAHhWNBIAAAAAAAAAANwFAAAi" + 125 "AAAAcAAAAAkAAAD4AAAABAAAABwBAAABAAAATAEAAAcAAABUAQAAAQAAAIwBAAD0BAAArAEAAKwB" + 126 "AACvAQAAsgEAALoBAAC+AQAAxAEAAMwBAADrAQAAIQIAAFgCAACQAgAAvgIAAOICAAACAwAAIQMA" + 127 "ADUDAABLAwAAXwMAAIADAACgAwAAwAMAAN8DAADmAwAA8QMAAPQDAAD4AwAAAAQAAA0EAAAgBAAA" + 128 "MQQAADcEAABBBAAARgQAAE0EAAAIAAAACQAAAAoAAAALAAAADAAAAA0AAAAOAAAADwAAABcAAAAX" + 129 "AAAACAAAAAAAAAAYAAAACAAAAFQEAAAYAAAACAAAAFwEAAAYAAAACAAAAGQEAAABAAAAHgAAAAAA" + 130 "AgAZAAAAAQABAAIAAAABAAAABQAAAAEAAAAVAAAAAQADACAAAAAGAAAAAgAAAAcAAAAfAAAAAQAA" + 131 "AAAAAAAGAAAAAAAAAAYAAAC8BQAAWAUAAAAAAAABKAABPAAGPGluaXQ+AAI+OwAEPjspVgAGRmlu" + 132 "aXNoAB1Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3QuamF2YQA0TGFuZHJvaWQvanZtdGkvY3RzL0p2" + 133 "bXRpUmVkZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcgA1TGFuZHJvaWQvanZtdGkvY3RzL0p2bXRp" + 134 "UmVkZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcjsANkxhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJl" + 135 "ZGVmaW5lQ2xhc3Nlc1Rlc3QkVHJhbnNmb3JtOwAsTGFuZHJvaWQvanZtdGkvY3RzL0p2bXRpUmVk" + 136 "ZWZpbmVDbGFzc2VzVGVzdDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxk" + 137 "YWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAdTGRhbHZpay9hbm5vdGF0aW9uL1NpZ25hdHVy" + 138 "ZTsAEkxqYXZhL2xhbmcvT2JqZWN0OwAUTGphdmEvbGFuZy9SdW5uYWJsZTsAEkxqYXZhL2xhbmcv" + 139 "U3RyaW5nOwAfUG9zdCBGaW5pc2ggcHJpdmF0ZSBtZXRob2QgY2FsbAAeUG9zdCBTdGFydCBwcml2" + 140 "YXRlIG1ldGhvZCBjYWxsAB5QcmUgRmluaXNoIHByaXZhdGUgbWV0aG9kIGNhbGwAHVByZSBTdGFy" + 141 "dCBwcml2YXRlIG1ldGhvZCBjYWxsAAVTdGFydAAJVHJhbnNmb3JtAAFWAAJWTAAGYWNjZXB0AAth" + 142 "Y2Nlc3NGbGFncwARZ29vZGJ5ZSAtIHByaXZhdGUAD2hlbGxvIC0gcHJpdmF0ZQAEbmFtZQAIcmVw" + 143 "b3J0ZXIAA3J1bgAFc2F5SGkABXZhbHVlAAEAAAAAAAAAAQAAAAYAAAABAAAABwAAAAwBAAcOPC0A" + 144 "FQAHDocAEQAHDocAGQEABw6HPIc8hzyHAAAAAAIAAgABAAAAbAQAAAYAAABwEAUAAABbAQAADgAD" + 145 "AAEAAgAAAHQEAAAJAAAAVCAAABsBGwAAAHIgAAAQAA4AAAADAAEAAgAAAHoEAAAJAAAAVCAAABsB" + 146 "HAAAAHIgAAAQAA4AAAAEAAIAAgAAAIAEAAAqAAAAVCAAABsBFAAAAHIgAAAQAHAQAwACAFQgAAAb" + 147 "ARIAAAByIAAAEAByEAYAAwBUIAAAGwETAAAAciAAABAAcBACAAIAVCAAABsBEQAAAHIgAAAQAA4A" + 148 "AAEDAQACAYGABJAJAQKsCQEC0AkEAfQJAgMBIRgCAgQCGgQIHRcWAgUBIRwEFwcXARcQFwMCBQEh" + 149 "HAUXABcHFwEXEBcEAAAAAgAAAHAFAAB2BQAAAQAAAH8FAAABAAAAjQUAAKAFAAABAAAAAQAAAAAA" + 150 "AAAAAAAArAUAAAEAAAC0BQAAEAAAAAAAAAABAAAAAAAAAAEAAAAiAAAAcAAAAAIAAAAJAAAA+AAA" + 151 "AAMAAAAEAAAAHAEAAAQAAAABAAAATAEAAAUAAAAHAAAAVAEAAAYAAAABAAAAjAEAAAIgAAAiAAAA" + 152 "rAEAAAEQAAADAAAAVAQAAAMgAAAEAAAAbAQAAAEgAAAEAAAAkAQAAAAgAAABAAAAWAUAAAQgAAAE" + 153 "AAAAcAUAAAMQAAADAAAAoAUAAAYgAAABAAAAvAUAAAAQAAABAAAA3AUAAA=="); 154 155 /** 156 * Base64 encoded dex file containing the following inner class. 157 * <code> 158 * // NB This has the actual name Landroid/jvmti/cts/JvmtiRedefineClassesTest$Transform; 159 * static class Transform { 160 * // NB This field has type Landroid/jvmti/cts/JvmtiRedefineClassesTest$Consumer; 161 * private Consumer<String> reporter; 162 * public Transform(Consumer<String> reporter) { 163 * this.reporter = reporter; 164 * } 165 * private void Start() { 166 * reporter.accept("TRANSFORMED - Hello - private"); 167 * } 168 * private void Finish() { 169 * reporter.accept("TRANSFORMED - Goodbye - private"); 170 * } 171 * public void sayHi(Runnable r) { 172 * reporter.accept("TRANSFORMED - pre Start private method call"); 173 * Start(); 174 * reporter.accept("TRANSFORMED - post Start private method call"); 175 * r.run(); 176 * reporter.accept("TRANSFORMED - pre Finish private method call"); 177 * Finish(); 178 * reporter.accept("TRANSFORMED - post Finish private method call"); 179 * } 180 * } 181 * </code> 182 */ 183 private static final RedefineError GOOD_TRANSFORM = new RedefineError( 184 JvmtiErrors.NONE, Transform.class, 185 "ZGV4CjAzNQBmR3TRAAAAAAAAAAAAAAAAAAAAAAAAAAD0BgAAcAAAAHhWNBIAAAAAAAAAADAGAAAi" + 186 "AAAAcAAAAAkAAAD4AAAABAAAABwBAAABAAAATAEAAAcAAABUAQAAAQAAAIwBAABIBQAArAEAAKwB" + 187 "AACvAQAAsgEAALoBAAC+AQAAxAEAAMwBAADrAQAAIQIAAFgCAACQAgAAvgIAAOICAAACAwAAIQMA" + 188 "ADUDAABLAwAAXwMAAGYDAACHAwAApgMAANUDAAADBAAAMQQAAF4EAABpBAAAbAQAAHAEAAB4BAAA" + 189 "hQQAAIsEAACVBAAAmgQAAKEEAAAIAAAACQAAAAoAAAALAAAADAAAAA0AAAAOAAAADwAAABkAAAAZ" + 190 "AAAACAAAAAAAAAAaAAAACAAAAKgEAAAaAAAACAAAALAEAAAaAAAACAAAALgEAAABAAAAHgAAAAAA" + 191 "AgAbAAAAAQABAAIAAAABAAAABQAAAAEAAAARAAAAAQADACAAAAAGAAAAAgAAAAcAAAAfAAAAAQAA" + 192 "AAAAAAAGAAAAAAAAAAYAAAAQBgAArAUAAAAAAAABKAABPAAGPGluaXQ+AAI+OwAEPjspVgAGRmlu" + 193 "aXNoAB1Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3QuamF2YQA0TGFuZHJvaWQvanZtdGkvY3RzL0p2" + 194 "bXRpUmVkZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcgA1TGFuZHJvaWQvanZtdGkvY3RzL0p2bXRp" + 195 "UmVkZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcjsANkxhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJl" + 196 "ZGVmaW5lQ2xhc3Nlc1Rlc3QkVHJhbnNmb3JtOwAsTGFuZHJvaWQvanZtdGkvY3RzL0p2bXRpUmVk" + 197 "ZWZpbmVDbGFzc2VzVGVzdDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxk" + 198 "YWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAdTGRhbHZpay9hbm5vdGF0aW9uL1NpZ25hdHVy" + 199 "ZTsAEkxqYXZhL2xhbmcvT2JqZWN0OwAUTGphdmEvbGFuZy9SdW5uYWJsZTsAEkxqYXZhL2xhbmcv" + 200 "U3RyaW5nOwAFU3RhcnQAH1RSQU5TRk9STUVEIC0gR29vZGJ5ZSAtIHByaXZhdGUAHVRSQU5TRk9S" + 201 "TUVEIC0gSGVsbG8gLSBwcml2YXRlAC1UUkFOU0ZPUk1FRCAtIHBvc3QgRmluaXNoIHByaXZhdGUg" + 202 "bWV0aG9kIGNhbGwALFRSQU5TRk9STUVEIC0gcG9zdCBTdGFydCBwcml2YXRlIG1ldGhvZCBjYWxs" + 203 "ACxUUkFOU0ZPUk1FRCAtIHByZSBGaW5pc2ggcHJpdmF0ZSBtZXRob2QgY2FsbAArVFJBTlNGT1JN" + 204 "RUQgLSBwcmUgU3RhcnQgcHJpdmF0ZSBtZXRob2QgY2FsbAAJVHJhbnNmb3JtAAFWAAJWTAAGYWNj" + 205 "ZXB0AAthY2Nlc3NGbGFncwAEbmFtZQAIcmVwb3J0ZXIAA3J1bgAFc2F5SGkABXZhbHVlAAEAAAAA" + 206 "AAAAAQAAAAYAAAABAAAABwAAAAsBAAcOPC0AFAAHDocAEAAHDocAGAEABw6HPIc8hzyHAAAAAAIA" + 207 "AgABAAAAwAQAAAYAAABwEAUAAABbAQAADgADAAEAAgAAAMgEAAAJAAAAVCAAABsBEgAAAHIgAAAQ" + 208 "AA4AAAADAAEAAgAAAM4EAAAJAAAAVCAAABsBEwAAAHIgAAAQAA4AAAAEAAIAAgAAANQEAAAqAAAA" + 209 "VCAAABsBFwAAAHIgAAAQAHAQAwACAFQgAAAbARUAAAByIAAAEAByEAYAAwBUIAAAGwEWAAAAciAA" + 210 "ABAAcBACAAIAVCAAABsBFAAAAHIgAAAQAA4AAAEDAQACAYGABOQJAQKACgECpAoEAcgKAgMBIRgC" + 211 "AgQCHAQIHRcYAgUBIRwEFwcXARcQFwMCBQEhHAUXABcHFwEXEBcEAAAAAgAAAMQFAADKBQAAAQAA" + 212 "ANMFAAABAAAA4QUAAPQFAAABAAAAAQAAAAAAAAAAAAAAAAYAAAEAAAAIBgAAEAAAAAAAAAABAAAA" + 213 "AAAAAAEAAAAiAAAAcAAAAAIAAAAJAAAA+AAAAAMAAAAEAAAAHAEAAAQAAAABAAAATAEAAAUAAAAH" + 214 "AAAAVAEAAAYAAAABAAAAjAEAAAIgAAAiAAAArAEAAAEQAAADAAAAqAQAAAMgAAAEAAAAwAQAAAEg" + 215 "AAAEAAAA5AQAAAAgAAABAAAArAUAAAQgAAAEAAAAxAUAAAMQAAADAAAA9AUAAAYgAAABAAAAEAYA" + 216 "AAAQAAABAAAAMAYAAA=="); 217 218 /** 219 * Tests that we can redefine Transform class from INITIAL_TRANSFORM to GOOD_TRANSFORM. 220 * <p> 221 * It uses doRedefine to do the transformation. 222 */ checkRedefinedTransform(Runnable doRedefine)223 private void checkRedefinedTransform(Runnable doRedefine) { 224 // The consumer that we use to observe the changes to the Transform class. 225 final StringCollector c = new StringCollector(); 226 Transform t = new Transform(c); 227 // Run once without changes. 228 t.sayHi(new Runnable() { 229 public void run() { 230 c.accept("Initial test run. No changes."); 231 } 232 }); 233 // Run once with obsolete methods. 234 t.sayHi(new Runnable() { 235 public void run() { 236 c.accept("Redefining calling function."); 237 doRedefine.run(); 238 } 239 }); 240 // Run once with new definition. 241 t.sayHi(new Runnable() { 242 public void run() { 243 c.accept("Final test run."); 244 } 245 }); 246 247 String[] output = c.reports.toArray(new String[0]); 248 assertArrayEquals( 249 new String[]{ 250 // The first call to sayHi 251 "Pre Start private method call", 252 "hello - private", 253 "Post Start private method call", 254 "Initial test run. No changes.", 255 "Pre Finish private method call", 256 "goodbye - private", 257 "Post Finish private method call", 258 259 // The second call to sayHi. 260 "Pre Start private method call", 261 "hello - private", 262 "Post Start private method call", 263 "Redefining calling function.", 264 "Pre Finish private method call", 265 "TRANSFORMED - Goodbye - private", 266 "Post Finish private method call", 267 268 // The final call to sayHi. 269 "TRANSFORMED - pre Start private method call", 270 "TRANSFORMED - Hello - private", 271 "TRANSFORMED - post Start private method call", 272 "Final test run.", 273 "TRANSFORMED - pre Finish private method call", 274 "TRANSFORMED - Goodbye - private", 275 "TRANSFORMED - post Finish private method call", 276 }, output); 277 } 278 279 @Test testSucessfulRedefine()280 public void testSucessfulRedefine() throws Exception { 281 checkRedefinedTransform(new Runnable() { 282 public void run() { 283 checkRedefinition(GOOD_TRANSFORM); 284 } 285 }); 286 } 287 288 @Test testSucessfulRetransform()289 public void testSucessfulRetransform() throws Exception { 290 pushTransformationResult(GOOD_TRANSFORM.target, GOOD_TRANSFORM.dexData); 291 checkRedefinedTransform(new Runnable() { 292 public void run() { 293 setTransformationEvent(true); 294 assertEquals(JvmtiErrors.NONE, retransformClass(Transform.class)); 295 } 296 }); 297 } 298 299 // This is a class that we will transform for tests. 300 // NB This has the actual name Landroid/jvmti/cts/JvmtiRedefineClassesTest$Transform2; 301 static class Transform2 { sayHi()302 public void sayHi() { 303 Assert.fail("Should not be called!"); 304 } 305 } 306 307 /** 308 * Test cases for failing redefines. 309 */ 310 private static final RedefineError[] FAILING_DEX_FILES = { 311 /** 312 * Base64 for this class. 313 * 314 * .class Landroid/jvmti/cts/JvmtiRedefineClassesTest$Transform2; 315 * .super Ljava/lang/Object; 316 * .source "JvmtiRedefineClassesTest.java" 317 * 318 * # annotations 319 * .annotation system Ldalvik/annotation/EnclosingClass; 320 * value = Landroid/jvmti/cts/JvmtiRedefineClassesTest; 321 * .end annotation 322 * 323 * .annotation system Ldalvik/annotation/InnerClass; 324 * accessFlags = 0x8 325 * name = "Transform2" 326 * .end annotation 327 * 328 * # direct methods 329 * .method constructor <init>()V 330 * .registers 1 331 * .prologue 332 * .line 33 333 * invoke-direct {p0}, Ljava/lang/Object;-><init>()V 334 * return-void 335 * .end method 336 * 337 * # virtual methods 338 * .method public sayHi()V 339 * .registers 1 340 * .prologue 341 * .line 35 342 * return-object v0 343 * .end method 344 */ 345 new RedefineError(JvmtiErrors.FAILS_VERIFICATION, Transform2.class, 346 "ZGV4CjAzNQBOhefYdQRcgqmkwhWsSyzb5I3udX0SnJ44AwAAcAAAAHhWNBIAAAAAAAAAAIwCAAAN" + 347 "AAAAcAAAAAYAAACkAAAAAQAAALwAAAAAAAAAAAAAAAMAAADIAAAAAQAAAOAAAAA4AgAAAAEAAAAB" + 348 "AAAIAQAAJwEAAGABAACOAQAAsgEAANIBAADmAQAA8gEAAPUBAAACAgAACAIAAA8CAAACAAAAAwAA" + 349 "AAQAAAAFAAAABgAAAAgAAAAIAAAABQAAAAAAAAAAAAAAAAAAAAAAAAALAAAABAAAAAAAAAAAAAAA" + 350 "AAAAAAQAAAAAAAAAAQAAADgCAAB+AgAAAAAAAAY8aW5pdD4AHUp2bXRpUmVkZWZpbmVDbGFzc2Vz" + 351 "VGVzdC5qYXZhADdMYW5kcm9pZC9qdm10aS9jdHMvSnZtdGlSZWRlZmluZUNsYXNzZXNUZXN0JFRy" + 352 "YW5zZm9ybTI7ACxMYW5kcm9pZC9qdm10aS9jdHMvSnZtdGlSZWRlZmluZUNsYXNzZXNUZXN0OwAi" + 353 "TGRhbHZpay9hbm5vdGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0aW9uL0lu" + 354 "bmVyQ2xhc3M7ABJMamF2YS9sYW5nL09iamVjdDsAClRyYW5zZm9ybTIAAVYAC2FjY2Vzc0ZsYWdz" + 355 "AARuYW1lAAVzYXlIaQAFdmFsdWUAAAACAwIJBAgKFwcCAgEMGAEAAAAAAAIAAAAhAgAAGAIAACwC" + 356 "AAAAAAAAAAAAAAAAAAAhAAcOACMABw4AAAABAAEAAQAAAEgCAAAEAAAAcBACAAAADgACAAEAAAAA" + 357 "AE0CAAABAAAAEQAAAAEBAICABNQEAQHsBA4AAAAAAAAAAQAAAAAAAAABAAAADQAAAHAAAAACAAAA" + 358 "BgAAAKQAAAADAAAAAQAAALwAAAAFAAAAAwAAAMgAAAAGAAAAAQAAAOAAAAACIAAADQAAAAABAAAE" + 359 "IAAAAgAAABgCAAADEAAAAgAAACgCAAAGIAAAAQAAADgCAAADIAAAAgAAAEgCAAABIAAAAgAAAFQC" + 360 "AAAAIAAAAQAAAH4CAAAAEAAAAQAAAIwCAAA="), 361 /** 362 * Base64 for this class. 363 * 364 * static class Transform { 365 * private Consumer<String> reporter; 366 * public Transform(Consumer<String> reporter) { 367 * this.reporter = reporter; 368 * } 369 * private void Start() { } 370 * private void Finish() { } 371 * protected void sayHi(Runnable r) { } 372 * } 373 */ 374 new RedefineError( 375 JvmtiErrors.UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED, Transform.class, 376 "ZGV4CjAzNQAf2DrkAAAAAAAAAAAAAAAAAAAAAAAAAAAwBQAAcAAAAHhWNBIAAAAAAAAAAGwEAAAa" + 377 "AAAAcAAAAAkAAADYAAAAAwAAAPwAAAABAAAAIAEAAAUAAAAoAQAAAQAAAFABAADAAwAAcAEAAHAB" + 378 "AABzAQAAdgEAAH4BAACCAQAAiAEAAJABAACvAQAA5QEAABwCAABUAgAAggIAAKYCAADGAgAA5QIA" + 379 "APkCAAAPAwAAIwMAACoDAAA1AwAAOAMAADwDAABJAwAATwMAAFkDAABgAwAACAAAAAkAAAAKAAAA" + 380 "CwAAAAwAAAANAAAADgAAAA8AAAATAAAAEwAAAAgAAAAAAAAAFAAAAAgAAABoAwAAFAAAAAgAAABw" + 381 "AwAAAQAAABcAAAABAAEAAgAAAAEAAAAFAAAAAQAAABEAAAABAAIAGAAAAAYAAAACAAAAAQAAAAAA" + 382 "AAAGAAAAAAAAAAYAAABMBAAA6AMAAAAAAAABKAABPAAGPGluaXQ+AAI+OwAEPjspVgAGRmluaXNo" + 383 "AB1Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3QuamF2YQA0TGFuZHJvaWQvanZtdGkvY3RzL0p2bXRp" + 384 "UmVkZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcgA1TGFuZHJvaWQvanZtdGkvY3RzL0p2bXRpUmVk" + 385 "ZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcjsANkxhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJlZGVm" + 386 "aW5lQ2xhc3Nlc1Rlc3QkVHJhbnNmb3JtOwAsTGFuZHJvaWQvanZtdGkvY3RzL0p2bXRpUmVkZWZp" + 387 "bmVDbGFzc2VzVGVzdDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2" + 388 "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAdTGRhbHZpay9hbm5vdGF0aW9uL1NpZ25hdHVyZTsA" + 389 "EkxqYXZhL2xhbmcvT2JqZWN0OwAUTGphdmEvbGFuZy9SdW5uYWJsZTsAEkxqYXZhL2xhbmcvU3Ry" + 390 "aW5nOwAFU3RhcnQACVRyYW5zZm9ybQABVgACVkwAC2FjY2Vzc0ZsYWdzAARuYW1lAAhyZXBvcnRl" + 391 "cgAFc2F5SGkABXZhbHVlAAABAAAAAAAAAAEAAAAHAAAACwEABw48LQARAAcOAA8ABw4AEwEABw4A" + 392 "AgACAAEAAAB4AwAABgAAAHAQBAAAAFsBAAAOAAEAAQAAAAAAgAMAAAEAAAAOAAAAAQABAAAAAACF" + 393 "AwAAAQAAAA4AAAACAAIAAAAAAIoDAAABAAAADgAAAAABAwEAAgCBgASQBwECrAcBAsAHAwTUBwID" + 394 "ARkYAgIEAhUECBYXEgIFARkcBBcHFwEXEBcDAgUBGRwFFwAXBxcBFxAXBAAAAAIAAAAABAAABgQA" + 395 "AAEAAAAPBAAAAQAAAB0EAAAwBAAAAQAAAAEAAAAAAAAAAAAAADwEAAAAAAAARAQAABAAAAAAAAAA" + 396 "AQAAAAAAAAABAAAAGgAAAHAAAAACAAAACQAAANgAAAADAAAAAwAAAPwAAAAEAAAAAQAAACABAAAF" + 397 "AAAABQAAACgBAAAGAAAAAQAAAFABAAACIAAAGgAAAHABAAABEAAAAgAAAGgDAAADIAAABAAAAHgD" + 398 "AAABIAAABAAAAJADAAAAIAAAAQAAAOgDAAAEIAAABAAAAAAEAAADEAAAAwAAADAEAAAGIAAAAQAA" + 399 "AEwEAAAAEAAAAQAAAGwEAAA="), 400 /** 401 * Base64 for this class. 402 * 403 * static final class Transform { 404 * private Consumer<String> reporter; 405 * public Transform(Consumer<String> reporter) { 406 * this.reporter = reporter; 407 * } 408 * private void Start() { } 409 * private void Finish() { } 410 * public void sayHi(Runnable r) { } 411 * } 412 */ 413 new RedefineError( 414 JvmtiErrors.UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED, Transform.class, 415 "ZGV4CjAzNQA82MAwAAAAAAAAAAAAAAAAAAAAAAAAAAAwBQAAcAAAAHhWNBIAAAAAAAAAAGwEAAAa" + 416 "AAAAcAAAAAkAAADYAAAAAwAAAPwAAAABAAAAIAEAAAUAAAAoAQAAAQAAAFABAADAAwAAcAEAAHAB" + 417 "AABzAQAAdgEAAH4BAACCAQAAiAEAAJABAACvAQAA5QEAABwCAABUAgAAggIAAKYCAADGAgAA5QIA" + 418 "APkCAAAPAwAAIwMAACoDAAA1AwAAOAMAADwDAABJAwAATwMAAFkDAABgAwAACAAAAAkAAAAKAAAA" + 419 "CwAAAAwAAAANAAAADgAAAA8AAAATAAAAEwAAAAgAAAAAAAAAFAAAAAgAAABoAwAAFAAAAAgAAABw" + 420 "AwAAAQAAABcAAAABAAEAAgAAAAEAAAAFAAAAAQAAABEAAAABAAIAGAAAAAYAAAACAAAAAQAAABAA" + 421 "AAAGAAAAAAAAAAYAAABMBAAA6AMAAAAAAAABKAABPAAGPGluaXQ+AAI+OwAEPjspVgAGRmluaXNo" + 422 "AB1Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3QuamF2YQA0TGFuZHJvaWQvanZtdGkvY3RzL0p2bXRp" + 423 "UmVkZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcgA1TGFuZHJvaWQvanZtdGkvY3RzL0p2bXRpUmVk" + 424 "ZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcjsANkxhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJlZGVm" + 425 "aW5lQ2xhc3Nlc1Rlc3QkVHJhbnNmb3JtOwAsTGFuZHJvaWQvanZtdGkvY3RzL0p2bXRpUmVkZWZp" + 426 "bmVDbGFzc2VzVGVzdDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2" + 427 "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAdTGRhbHZpay9hbm5vdGF0aW9uL1NpZ25hdHVyZTsA" + 428 "EkxqYXZhL2xhbmcvT2JqZWN0OwAUTGphdmEvbGFuZy9SdW5uYWJsZTsAEkxqYXZhL2xhbmcvU3Ry" + 429 "aW5nOwAFU3RhcnQACVRyYW5zZm9ybQABVgACVkwAC2FjY2Vzc0ZsYWdzAARuYW1lAAhyZXBvcnRl" + 430 "cgAFc2F5SGkABXZhbHVlAAABAAAAAAAAAAEAAAAHAAAACwEABw48LQARAAcOAA8ABw4AEwEABw4A" + 431 "AgACAAEAAAB4AwAABgAAAHAQBAAAAFsBAAAOAAEAAQAAAAAAgAMAAAEAAAAOAAAAAQABAAAAAACF" + 432 "AwAAAQAAAA4AAAACAAIAAAAAAIoDAAABAAAADgAAAAABAwEAAgCBgASQBwECrAcBAsAHAwHUBwID" + 433 "ARkYAgIEAhUEGBYXEgIFARkcBBcHFwEXEBcDAgUBGRwFFwAXBxcBFxAXBAAAAAIAAAAABAAABgQA" + 434 "AAEAAAAPBAAAAQAAAB0EAAAwBAAAAQAAAAEAAAAAAAAAAAAAADwEAAAAAAAARAQAABAAAAAAAAAA" + 435 "AQAAAAAAAAABAAAAGgAAAHAAAAACAAAACQAAANgAAAADAAAAAwAAAPwAAAAEAAAAAQAAACABAAAF" + 436 "AAAABQAAACgBAAAGAAAAAQAAAFABAAACIAAAGgAAAHABAAABEAAAAgAAAGgDAAADIAAABAAAAHgD" + 437 "AAABIAAABAAAAJADAAAAIAAAAQAAAOgDAAAEIAAABAAAAAAEAAADEAAAAwAAADAEAAAGIAAAAQAA" + 438 "AEwEAAAAEAAAAQAAAGwEAAA="), 439 /** 440 * Base64 for this class. 441 * 442 * static class Transform { 443 * private Consumer<String> reporter; 444 * public Transform(Consumer<String> reporter) { 445 * this.reporter = reporter; 446 * } 447 * private void Finish() { } 448 * public void sayHi(Runnable r) { } 449 * } 450 */ 451 new RedefineError( 452 JvmtiErrors.UNSUPPORTED_REDEFINITION_METHOD_DELETED, Transform.class, 453 "ZGV4CjAzNQBG028hAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAcAAAAHhWNBIAAAAAAAAAADwEAAAZ" + 454 "AAAAcAAAAAkAAADUAAAAAwAAAPgAAAABAAAAHAEAAAQAAAAkAQAAAQAAAEQBAACcAwAAZAEAAGQB" + 455 "AABnAQAAagEAAHIBAAB2AQAAfAEAAJsBAADRAQAACAIAAEACAABuAgAAkgIAALICAADRAgAA5QIA" + 456 "APsCAAAPAwAAFgMAACEDAAAkAwAAKAMAADUDAAA7AwAARQMAAEwDAAAHAAAACAAAAAkAAAAKAAAA" + 457 "CwAAAAwAAAANAAAADgAAABIAAAASAAAACAAAAAAAAAATAAAACAAAAFQDAAATAAAACAAAAFwDAAAB" + 458 "AAAAFgAAAAEAAQACAAAAAQAAABAAAAABAAIAFwAAAAYAAAACAAAAAQAAAAAAAAAGAAAAAAAAAAUA" + 459 "AAAcBAAAvAMAAAAAAAABKAABPAAGPGluaXQ+AAI+OwAEPjspVgAdSnZtdGlSZWRlZmluZUNsYXNz" + 460 "ZXNUZXN0LmphdmEANExhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3Qk" + 461 "Q29uc3VtZXIANUxhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3QkQ29u" + 462 "c3VtZXI7ADZMYW5kcm9pZC9qdm10aS9jdHMvSnZtdGlSZWRlZmluZUNsYXNzZXNUZXN0JFRyYW5z" + 463 "Zm9ybTsALExhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3Q7ACJMZGFs" + 464 "dmlrL2Fubm90YXRpb24vRW5jbG9zaW5nQ2xhc3M7AB5MZGFsdmlrL2Fubm90YXRpb24vSW5uZXJD" + 465 "bGFzczsAHUxkYWx2aWsvYW5ub3RhdGlvbi9TaWduYXR1cmU7ABJMamF2YS9sYW5nL09iamVjdDsA" + 466 "FExqYXZhL2xhbmcvUnVubmFibGU7ABJMamF2YS9sYW5nL1N0cmluZzsABVN0YXJ0AAlUcmFuc2Zv" + 467 "cm0AAVYAAlZMAAthY2Nlc3NGbGFncwAEbmFtZQAIcmVwb3J0ZXIABXNheUhpAAV2YWx1ZQAAAQAA" + 468 "AAAAAAABAAAABwAAAA0BAAcOAA4ABw4AEAEABw4AAAAAAgACAAEAAABkAwAABgAAAHAQAwAAAFsB" + 469 "AAAOAAEAAQAAAAAAagMAAAEAAAAOAAAAAgACAAAAAABvAwAAAQAAAA4AAAAAAQIBAAIAgYAE+AYB" + 470 "ApQHAgGoBwIDARgYAgIEAhQECBUXEQIFARgcBBcGFwEXDxcDAgUBGBwFFwAXBhcBFw8XBAAAAAIA" + 471 "AADQAwAA1gMAAAEAAADfAwAAAQAAAO0DAAAABAAAAQAAAAEAAAAAAAAAAAAAAAwEAAAAAAAAFAQA" + 472 "ABAAAAAAAAAAAQAAAAAAAAABAAAAGQAAAHAAAAACAAAACQAAANQAAAADAAAAAwAAAPgAAAAEAAAA" + 473 "AQAAABwBAAAFAAAABAAAACQBAAAGAAAAAQAAAEQBAAACIAAAGQAAAGQBAAABEAAAAgAAAFQDAAAD" + 474 "IAAAAwAAAGQDAAABIAAAAwAAAHgDAAAAIAAAAQAAALwDAAAEIAAABAAAANADAAADEAAAAwAAAAAE" + 475 "AAAGIAAAAQAAABwEAAAAEAAAAQAAADwEAAA="), 476 /** 477 * Base6is class. 478 * 479 * static class Transform { 480 * private Consumer<String> reporter; 481 * public Transform(Consumer<String> reporter) { 482 * this.reporter = reporter; 483 * } 484 * private void Start() { } 485 * private void Start2() { } 486 * private void Finish() { } 487 * public void sayHi(Runnable r) { } 488 * } 489 */ 490 new RedefineError( 491 JvmtiErrors.UNSUPPORTED_REDEFINITION_METHOD_ADDED, Transform.class, 492 "ZGV4CjAzNQC43HElAAAAAAAAAAAAAAAAAAAAAAAAAABgBQAAcAAAAHhWNBIAAAAAAAAAAJwEAAAb" + 493 "AAAAcAAAAAkAAADcAAAAAwAAAAABAAABAAAAJAEAAAYAAAAsAQAAAQAAAFwBAADkAwAAfAEAAHwB" + 494 "AAB/AQAAggEAAIoBAACOAQAAlAEAAJwBAAC7AQAA8QEAACgCAABgAgAAjgIAALICAADSAgAA8QIA" + 495 "AAUDAAAbAwAALwMAADYDAAA+AwAASQMAAEwDAABQAwAAXQMAAGMDAABtAwAAdAMAAAgAAAAJAAAA" + 496 "CgAAAAsAAAAMAAAADQAAAA4AAAAPAAAAFAAAABQAAAAIAAAAAAAAABUAAAAIAAAAfAMAABUAAAAI" + 497 "AAAAhAMAAAEAAAAYAAAAAQABAAIAAAABAAAABQAAAAEAAAARAAAAAQAAABIAAAABAAIAGQAAAAYA" + 498 "AAACAAAAAQAAAAAAAAAGAAAAAAAAAAYAAAB8BAAAFAQAAAAAAAABKAABPAAGPGluaXQ+AAI+OwAE" + 499 "PjspVgAGRmluaXNoAB1Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3QuamF2YQA0TGFuZHJvaWQvanZt" + 500 "dGkvY3RzL0p2bXRpUmVkZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcgA1TGFuZHJvaWQvanZtdGkv" + 501 "Y3RzL0p2bXRpUmVkZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcjsANkxhbmRyb2lkL2p2bXRpL2N0" + 502 "cy9Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3QkVHJhbnNmb3JtOwAsTGFuZHJvaWQvanZtdGkvY3Rz" + 503 "L0p2bXRpUmVkZWZpbmVDbGFzc2VzVGVzdDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdD" + 504 "bGFzczsAHkxkYWx2aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAdTGRhbHZpay9hbm5vdGF0aW9u" + 505 "L1NpZ25hdHVyZTsAEkxqYXZhL2xhbmcvT2JqZWN0OwAUTGphdmEvbGFuZy9SdW5uYWJsZTsAEkxq" + 506 "YXZhL2xhbmcvU3RyaW5nOwAFU3RhcnQABlN0YXJ0MgAJVHJhbnNmb3JtAAFWAAJWTAALYWNjZXNz" + 507 "RmxhZ3MABG5hbWUACHJlcG9ydGVyAAVzYXlIaQAFdmFsdWUAAAEAAAAAAAAAAQAAAAcAAAANAQAH" + 508 "DgAQAAcOAA4ABw4ADwAHDgARAQAHDgAAAgACAAEAAACMAwAABgAAAHAQBQAAAFsBAAAOAAEAAQAA" + 509 "AAAAkgMAAAEAAAAOAAAAAQABAAAAAACXAwAAAQAAAA4AAAABAAEAAAAAAJwDAAABAAAADgAAAAIA" + 510 "AgAAAAAAoQMAAAEAAAAOAAAAAAEEAQACAIGABKgHAQLEBwEC2AcBAuwHBAGACAIDARoYAgIEAhYE" + 511 "CBcXEwIFARocBBcHFwEXEBcDAgUBGhwFFwAXBxcBFxAXBAAAAAIAAAAwBAAANgQAAAEAAAA/BAAA" + 512 "AQAAAE0EAABgBAAAAQAAAAEAAAAAAAAAAAAAAGwEAAAAAAAAdAQAABAAAAAAAAAAAQAAAAAAAAAB" + 513 "AAAAGwAAAHAAAAACAAAACQAAANwAAAADAAAAAwAAAAABAAAEAAAAAQAAACQBAAAFAAAABgAAACwB" + 514 "AAAGAAAAAQAAAFwBAAACIAAAGwAAAHwBAAABEAAAAgAAAHwDAAADIAAABQAAAIwDAAABIAAABQAA" + 515 "AKgDAAAAIAAAAQAAABQEAAAEIAAABAAAADAEAAADEAAAAwAAAGAEAAAGIAAAAQAAAHwEAAAAEAAA" + 516 "AQAAAJwEAAA="), 517 /** 518 * Base64 for this class. 519 * 520 * static class Transform { 521 * public Transform(Consumer<String> reporter) { } 522 * private void Start() { } 523 * private void Finish() { } 524 * public void sayHi(Runnable r) { } 525 * } 526 */ 527 new RedefineError( 528 JvmtiErrors.UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED, Transform.class, 529 "ZGV4CjAzNQCn0K9/AAAAAAAAAAAAAAAAAAAAAAAAAADkBAAAcAAAAHhWNBIAAAAAAAAAACwEAAAY" + 530 "AAAAcAAAAAkAAADQAAAAAwAAAPQAAAAAAAAAAAAAAAUAAAAYAQAAAQAAAEABAACEAwAAYAEAAGAB" + 531 "AABjAQAAZgEAAG4BAAB0AQAAfAEAAJsBAADRAQAACAIAAEACAABuAgAAkgIAALICAADRAgAA5QIA" + 532 "APsCAAAPAwAAFgMAACEDAAAkAwAAKAMAADUDAAA7AwAAQgMAAAcAAAAIAAAACQAAAAoAAAALAAAA" + 533 "DAAAAA0AAAAOAAAAEgAAABIAAAAIAAAAAAAAABMAAAAIAAAATAMAABMAAAAIAAAAVAMAAAEAAQAC" + 534 "AAAAAQAAAAQAAAABAAAAEAAAAAEAAgAWAAAABgAAAAIAAAABAAAAAAAAAAYAAAAAAAAABQAAABQE" + 535 "AADIAwAAAAAAAAEoAAE8AAY8aW5pdD4ABD47KVYABkZpbmlzaAAdSnZtdGlSZWRlZmluZUNsYXNz" + 536 "ZXNUZXN0LmphdmEANExhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3Qk" + 537 "Q29uc3VtZXIANUxhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3QkQ29u" + 538 "c3VtZXI7ADZMYW5kcm9pZC9qdm10aS9jdHMvSnZtdGlSZWRlZmluZUNsYXNzZXNUZXN0JFRyYW5z" + 539 "Zm9ybTsALExhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3Q7ACJMZGFs" + 540 "dmlrL2Fubm90YXRpb24vRW5jbG9zaW5nQ2xhc3M7AB5MZGFsdmlrL2Fubm90YXRpb24vSW5uZXJD" + 541 "bGFzczsAHUxkYWx2aWsvYW5ub3RhdGlvbi9TaWduYXR1cmU7ABJMamF2YS9sYW5nL09iamVjdDsA" + 542 "FExqYXZhL2xhbmcvUnVubmFibGU7ABJMamF2YS9sYW5nL1N0cmluZzsABVN0YXJ0AAlUcmFuc2Zv" + 543 "cm0AAVYAAlZMAAthY2Nlc3NGbGFncwAEbmFtZQAFc2F5SGkABXZhbHVlAAAAAAEAAAAAAAAAAQAA" + 544 "AAcAAAAMAQAHDgAOAAcOAA0ABw4ADwEABw4AAAACAAIAAQAAAFwDAAAEAAAAcBAEAAAADgABAAEA" + 545 "AAAAAGIDAAABAAAADgAAAAEAAQAAAAAAZwMAAAEAAAAOAAAAAgACAAAAAABsAwAAAQAAAA4AAAAA" + 546 "AAMBAIGABPQGAQKMBwECoAcDAbQHAAACAwEXGAICBAIUBAgVFxECBQEXHAUXABcGFwEXDxcDAAIA" + 547 "AADgAwAA5gMAAAEAAADvAwAAAAQAAAAAAAABAAAAAAAAAAAAAAAMBAAADwAAAAAAAAABAAAAAAAA" + 548 "AAEAAAAYAAAAcAAAAAIAAAAJAAAA0AAAAAMAAAADAAAA9AAAAAUAAAAFAAAAGAEAAAYAAAABAAAA" + 549 "QAEAAAIgAAAYAAAAYAEAAAEQAAACAAAATAMAAAMgAAAEAAAAXAMAAAEgAAAEAAAAdAMAAAAgAAAB" + 550 "AAAAyAMAAAQgAAADAAAA4AMAAAMQAAACAAAAAAQAAAYgAAABAAAAFAQAAAAQAAABAAAALAQAAA=="), 551 /** 552 * Base64 for this class. 553 * 554 * static class Transform3 { 555 * // NB This field has type Landroid/jvmti/cts/JvmtiRedefineClassesTest$Consumer; 556 * private Consumer<String> reporter; 557 * public Transform3(Consumer<String> reporter) { this.reporter = reporter; } 558 * private void Start() { } 559 * private void Finish() { } 560 * public void sayHi(Runnable r) { } 561 * } 562 */ 563 new RedefineError( 564 JvmtiErrors.NAMES_DONT_MATCH, Transform.class, 565 "ZGV4CjAzNQCc2B3nAAAAAAAAAAAAAAAAAAAAAAAAAAA0BQAAcAAAAHhWNBIAAAAAAAAAAHAEAAAa" + 566 "AAAAcAAAAAkAAADYAAAAAwAAAPwAAAABAAAAIAEAAAUAAAAoAQAAAQAAAFABAADEAwAAcAEAAHAB" + 567 "AABzAQAAdgEAAH4BAACCAQAAiAEAAJABAACvAQAA5QEAABwCAABVAgAAgwIAAKcCAADHAgAA5gIA" + 568 "APoCAAAQAwAAJAMAACsDAAA3AwAAOgMAAD4DAABLAwAAUQMAAFsDAABiAwAACAAAAAkAAAAKAAAA" + 569 "CwAAAAwAAAANAAAADgAAAA8AAAATAAAAEwAAAAgAAAAAAAAAFAAAAAgAAABsAwAAFAAAAAgAAAB0" + 570 "AwAAAQAAABcAAAABAAEAAgAAAAEAAAAFAAAAAQAAABEAAAABAAIAGAAAAAYAAAACAAAAAQAAAAAA" + 571 "AAAGAAAAAAAAAAYAAABQBAAA7AMAAAAAAAABKAABPAAGPGluaXQ+AAI+OwAEPjspVgAGRmluaXNo" + 572 "AB1Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3QuamF2YQA0TGFuZHJvaWQvanZtdGkvY3RzL0p2bXRp" + 573 "UmVkZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcgA1TGFuZHJvaWQvanZtdGkvY3RzL0p2bXRpUmVk" + 574 "ZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcjsAN0xhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJlZGVm" + 575 "aW5lQ2xhc3Nlc1Rlc3QkVHJhbnNmb3JtMzsALExhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJlZGVm" + 576 "aW5lQ2xhc3Nlc1Rlc3Q7ACJMZGFsdmlrL2Fubm90YXRpb24vRW5jbG9zaW5nQ2xhc3M7AB5MZGFs" + 577 "dmlrL2Fubm90YXRpb24vSW5uZXJDbGFzczsAHUxkYWx2aWsvYW5ub3RhdGlvbi9TaWduYXR1cmU7" + 578 "ABJMamF2YS9sYW5nL09iamVjdDsAFExqYXZhL2xhbmcvUnVubmFibGU7ABJMamF2YS9sYW5nL1N0" + 579 "cmluZzsABVN0YXJ0AApUcmFuc2Zvcm0zAAFWAAJWTAALYWNjZXNzRmxhZ3MABG5hbWUACHJlcG9y" + 580 "dGVyAAVzYXlIaQAFdmFsdWUAAAAAAQAAAAAAAAABAAAABwAAAAwBAAcOAA4ABw4ADQAHDgAPAQAH" + 581 "DgAAAAIAAgABAAAAfAMAAAYAAABwEAQAAABbAQAADgABAAEAAAAAAIIDAAABAAAADgAAAAEAAQAA" + 582 "AAAAhwMAAAEAAAAOAAAAAgACAAAAAACMAwAAAQAAAA4AAAAAAQMBAAIAgYAElAcBArAHAQLEBwMB" + 583 "2AcCAwEZGAICBAIVBAgWFxICBQEZHAQXBxcBFxAXAwIFARkcBRcAFwcXARcQFwQAAAACAAAABAQA" + 584 "AAoEAAABAAAAEwQAAAEAAAAhBAAANAQAAAEAAAABAAAAAAAAAAAAAABABAAAAAAAAEgEAAAQAAAA" + 585 "AAAAAAEAAAAAAAAAAQAAABoAAABwAAAAAgAAAAkAAADYAAAAAwAAAAMAAAD8AAAABAAAAAEAAAAg" + 586 "AQAABQAAAAUAAAAoAQAABgAAAAEAAABQAQAAAiAAABoAAABwAQAAARAAAAIAAABsAwAAAyAAAAQA" + 587 "AAB8AwAAASAAAAQAAACUAwAAACAAAAEAAADsAwAABCAAAAQAAAAEBAAAAxAAAAMAAAA0BAAABiAA" + 588 "AAEAAABQBAAAABAAAAEAAABwBAAA"), 589 /** 590 * Base64 for this class. 591 * 592 * static class Transform extends Observable { 593 * // NB This field has type Landroid/jvmti/cts/JvmtiRedefineClassesTest$Consumer; 594 * private Consumer<String> reporter; 595 * public Transform(Consumer<String> reporter) { super(); this.reporter = reporter; } 596 * private void Start() { } 597 * private void Finish() { } 598 * public void sayHi(Runnable r) { } 599 * } 600 */ 601 new RedefineError( 602 JvmtiErrors.UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED, Transform.class, 603 "ZGV4CjAzNQAV2qEZAAAAAAAAAAAAAAAAAAAAAAAAAAA0BQAAcAAAAHhWNBIAAAAAAAAAAHAEAAAa" + 604 "AAAAcAAAAAkAAADYAAAAAwAAAPwAAAABAAAAIAEAAAUAAAAoAQAAAQAAAFABAADEAwAAcAEAAHAB" + 605 "AABzAQAAdgEAAH4BAACCAQAAiAEAAJABAACvAQAA5QEAABwCAABUAgAAggIAAKYCAADGAgAA5QIA" + 606 "APsCAAAPAwAAJwMAAC4DAAA5AwAAPAMAAEADAABNAwAAUwMAAF0DAABkAwAACAAAAAkAAAAKAAAA" + 607 "CwAAAAwAAAANAAAADgAAABAAAAATAAAAEwAAAAgAAAAAAAAAFAAAAAgAAABsAwAAFAAAAAgAAAB0" + 608 "AwAAAQAAABcAAAABAAEAAgAAAAEAAAAFAAAAAQAAABEAAAABAAIAGAAAAAcAAAACAAAAAQAAAAAA" + 609 "AAAHAAAAAAAAAAYAAABQBAAA7AMAAAAAAAABKAABPAAGPGluaXQ+AAI+OwAEPjspVgAGRmluaXNo" + 610 "AB1Kdm10aVJlZGVmaW5lQ2xhc3Nlc1Rlc3QuamF2YQA0TGFuZHJvaWQvanZtdGkvY3RzL0p2bXRp" + 611 "UmVkZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcgA1TGFuZHJvaWQvanZtdGkvY3RzL0p2bXRpUmVk" + 612 "ZWZpbmVDbGFzc2VzVGVzdCRDb25zdW1lcjsANkxhbmRyb2lkL2p2bXRpL2N0cy9Kdm10aVJlZGVm" + 613 "aW5lQ2xhc3Nlc1Rlc3QkVHJhbnNmb3JtOwAsTGFuZHJvaWQvanZtdGkvY3RzL0p2bXRpUmVkZWZp" + 614 "bmVDbGFzc2VzVGVzdDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2" + 615 "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAdTGRhbHZpay9hbm5vdGF0aW9uL1NpZ25hdHVyZTsA" + 616 "FExqYXZhL2xhbmcvUnVubmFibGU7ABJMamF2YS9sYW5nL1N0cmluZzsAFkxqYXZhL3V0aWwvT2Jz" + 617 "ZXJ2YWJsZTsABVN0YXJ0AAlUcmFuc2Zvcm0AAVYAAlZMAAthY2Nlc3NGbGFncwAEbmFtZQAIcmVw" + 618 "b3J0ZXIABXNheUhpAAV2YWx1ZQAAAQAAAAAAAAABAAAABgAAAA0BAAcOAA8ABw4ADgAHDgAQAQAH" + 619 "DgAAAAIAAgABAAAAfAMAAAYAAABwEAQAAABbAQAADgABAAEAAAAAAIIDAAABAAAADgAAAAEAAQAA" + 620 "AAAAhwMAAAEAAAAOAAAAAgACAAAAAACMAwAAAQAAAA4AAAAAAQMBAAIAgYAElAcBArAHAQLEBwMB" + 621 "2AcCAwEZGAICBAIVBAgWFxICBQEZHAQXBxcBFw8XAwIFARkcBRcAFwcXARcPFwQAAAACAAAABAQA" + 622 "AAoEAAABAAAAEwQAAAEAAAAhBAAANAQAAAEAAAABAAAAAAAAAAAAAABABAAAAAAAAEgEAAAQAAAA" + 623 "AAAAAAEAAAAAAAAAAQAAABoAAABwAAAAAgAAAAkAAADYAAAAAwAAAAMAAAD8AAAABAAAAAEAAAAg" + 624 "AQAABQAAAAUAAAAoAQAABgAAAAEAAABQAQAAAiAAABoAAABwAQAAARAAAAIAAABsAwAAAyAAAAQA" + 625 "AAB8AwAAASAAAAQAAACUAwAAACAAAAEAAADsAwAABCAAAAQAAAAEBAAAAxAAAAMAAAA0BAAABiAA" + 626 "AAEAAABQBAAAABAAAAEAAABwBAAA"), 627 /** 628 * Array classes are never modifiable. 629 * 630 * The base64 data is just an empty dex file. It has no classes associated with it. 631 */ 632 new RedefineError(JvmtiErrors.UNMODIFIABLE_CLASS, Transform[].class, 633 "ZGV4CjAzNQCRAy8PAAAAAAAAAAAAAAAAAAAAAAAAAACMAAAAcAAAAHhWNBIAAAAAAAAAAHAAAAAA" + 634 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAcAAAAAIA" + 635 "AAAAAAAAAQAAAAAAAAAAEAAAAQAAAHAAAAA="), 636 }; 637 638 @Test testRedefineFailures()639 public void testRedefineFailures() throws Exception { 640 // Just check each of the failing tests. 641 for (RedefineError e : FAILING_DEX_FILES) { 642 checkRedefinition(e); 643 } 644 } 645 checkRetransformation(RedefineError e)646 private void checkRetransformation(RedefineError e) { 647 clearTransformations(); 648 pushTransformationResult(e.target, e.dexData); 649 assertEquals(e.expectedError, retransformClass(e.target)); 650 } 651 652 @Test testRetransformFailures()653 public void testRetransformFailures() throws Exception { 654 setTransformationEvent(true); 655 setPopTransformations(true); 656 for (RedefineError e : FAILING_DEX_FILES) { 657 checkRetransformation(e); 658 } 659 } 660 661 private static final String ONLOAD_TEST_CLASS_NAME = 662 "android.jvmti.cts.memory_dex.TransformTarget"; 663 /** 664 * Base64 encoded version of the following class. 665 * package android.jvmti.cts.memory_dex; 666 * <p> 667 * public class TransformTarget { 668 * public void alpha() { } 669 * public void beta() { } 670 * } 671 */ 672 private static final byte[] ONLOAD_INITIAL_CLASS = Base64.getDecoder().decode( 673 "ZGV4CjAzNQAQT37mO0bz7SniP0I8RLnGvVsfM5ybXmdYAgAAcAAAAHhWNBIAAAAAAAAAANABAAAI" + 674 "AAAAcAAAAAMAAACQAAAAAQAAAJwAAAAAAAAAAAAAAAQAAACoAAAAAQAAAMgAAABwAQAA6AAAACgB" + 675 "AAAwAQAAYAEAAHQBAACKAQAAjQEAAJQBAACaAQAAAQAAAAIAAAAEAAAABAAAAAIAAAAAAAAAAAAA" + 676 "AAAAAAAAAAAABQAAAAAAAAAGAAAAAQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAwAAAAAAAAC9AQAA" + 677 "AAAAAAEAAQABAAAArgEAAAQAAABwEAMAAAAOAAEAAQAAAAAAswEAAAEAAAAOAAAAAQABAAAAAAC4" + 678 "AQAAAQAAAA4AAAAGPGluaXQ+AC5MYW5kcm9pZC9qdm10aS9jdHMvbWVtb3J5X2RleC9UcmFuc2Zv" + 679 "cm1UYXJnZXQ7ABJMamF2YS9sYW5nL09iamVjdDsAFFRyYW5zZm9ybVRhcmdldC5qYXZhAAFWAAVh" + 680 "bHBoYQAEYmV0YQASZW1pdHRlcjogamFjay00LjI4AAIABw4AAwAHDgAEAAcOAAAAAQIAgYAE6AEB" + 681 "AYACAQGUAgALAAAAAAAAAAEAAAAAAAAAAQAAAAgAAABwAAAAAgAAAAMAAACQAAAAAwAAAAEAAACc" + 682 "AAAABQAAAAQAAACoAAAABgAAAAEAAADIAAAAASAAAAMAAADoAAAAAiAAAAgAAAAoAQAAAyAAAAMA" + 683 "AACuAQAAACAAAAEAAAC9AQAAABAAAAEAAADQAQAA"); 684 /** 685 * Base64 encoded version of the following class. 686 * Note that this would be an illegal transformation if the class had been loaded as the first 687 * one. 688 * <p> 689 * package android.jvmti.cts.memory_dex; 690 * <p> 691 * public class TransformTarget { 692 * public void alpha(int abc) { 693 * } 694 * public int beta() { 695 * return 12; 696 * } 697 * public void gamma() { 698 * } 699 * } 700 */ 701 private static final byte[] ONLOAD_FINAL_CLASS = Base64.getDecoder().decode( 702 "ZGV4CjAzNQA5VqbusSyl8/G1EXrbm9uRuiHvkP4XixrMAgAAcAAAAHhWNBIAAAAAAAAAADgCAAAL" + 703 "AAAAcAAAAAQAAACcAAAAAwAAAKwAAAAAAAAAAAAAAAUAAADQAAAAAQAAAPgAAAC0AQAAGAEAAHYB" + 704 "AAB+AQAAgQEAALEBAADFAQAA2wEAAN4BAADiAQAA6QEAAO8BAAADAgAAAQAAAAIAAAADAAAABQAA" + 705 "AAEAAAAAAAAAAAAAAAUAAAADAAAAAAAAAAYAAAADAAAAcAEAAAEAAQAAAAAAAQACAAcAAAABAAAA" + 706 "CAAAAAEAAQAKAAAAAgABAAAAAAABAAAAAQAAAAIAAAAAAAAABAAAAAAAAAAfAgAAAAAAAAEAAQAB" + 707 "AAAACgIAAAQAAABwEAQAAAAOAAIAAgAAAAAADwIAAAEAAAAOAAAAAgABAAAAAAAVAgAAAwAAABMA" + 708 "DAAPAAAAAQABAAAAAAAaAgAAAQAAAA4AAAABAAAAAAAGPGluaXQ+AAFJAC5MYW5kcm9pZC9qdm10" + 709 "aS9jdHMvbWVtb3J5X2RleC9UcmFuc2Zvcm1UYXJnZXQ7ABJMamF2YS9sYW5nL09iamVjdDsAFFRy" + 710 "YW5zZm9ybVRhcmdldC5qYXZhAAFWAAJWSQAFYWxwaGEABGJldGEAEmVtaXR0ZXI6IGphY2stNC4y" + 711 "OAAFZ2FtbWEAAgAHDgAEAQAHDgAGAAcOAAkABw4AAAABAwCBgASYAgEBsAIBAcQCAQHcAgAAAAwA" + 712 "AAAAAAAAAQAAAAAAAAABAAAACwAAAHAAAAACAAAABAAAAJwAAAADAAAAAwAAAKwAAAAFAAAABQAA" + 713 "ANAAAAAGAAAAAQAAAPgAAAABIAAABAAAABgBAAABEAAAAQAAAHABAAACIAAACwAAAHYBAAADIAAA" + 714 "BAAAAAoCAAAAIAAAAQAAAB8CAAAAEAAAAQAAADgCAAA="); 715 716 private static class ExpectedMethod { 717 public final Class<?> returnType; 718 public final String name; 719 public final Class<?>[] params; 720 ExpectedMethod(Class<?> returnType, String name, Class<?>... params)721 public ExpectedMethod(Class<?> returnType, String name, Class<?>... params) { 722 this.returnType = returnType; 723 this.name = name; 724 this.params = params; 725 } 726 ensureHasMethod(Class<?> klass)727 public void ensureHasMethod(Class<?> klass) throws Exception { 728 try { 729 assertEquals(returnType, klass.getDeclaredMethod(name, params).getReturnType()); 730 } catch (NoSuchMethodException e) { 731 Assert.fail("Could not find method: " + klass + ": " + name + 732 " (params: " + Arrays.toString(params) + "). Reason was " + e); 733 } 734 } 735 } 736 checkClassHasMethods(Class<?> target, ExpectedMethod[] methods)737 private void checkClassHasMethods(Class<?> target, ExpectedMethod[] methods) throws Exception { 738 for (ExpectedMethod m : methods) { 739 m.ensureHasMethod(target); 740 } 741 } 742 743 @Test testCannotRetransformOnLoadTest()744 public void testCannotRetransformOnLoadTest() throws Exception { 745 // Just a sanity check along with below. 746 Class<?> target_class = new InMemoryDexClassLoader( 747 ByteBuffer.wrap(ONLOAD_INITIAL_CLASS), 748 getClass().getClassLoader()).loadClass(ONLOAD_TEST_CLASS_NAME); 749 checkClassHasMethods( 750 target_class, 751 new ExpectedMethod[]{ 752 new ExpectedMethod(Void.TYPE, "alpha"), 753 new ExpectedMethod(Void.TYPE, "beta"), 754 }); 755 assertTrue(JvmtiErrors.NONE != redefineClass(target_class, ONLOAD_FINAL_CLASS)); 756 } 757 758 @Test testRetransformOnLoad()759 public void testRetransformOnLoad() throws Exception { 760 pushTransformationResult(ONLOAD_TEST_CLASS_NAME.replace('.', '/'), ONLOAD_FINAL_CLASS); 761 setTransformationEvent(true); 762 setPopTransformations(false); 763 checkClassHasMethods( 764 new InMemoryDexClassLoader(ByteBuffer.wrap(ONLOAD_INITIAL_CLASS), 765 getClass().getClassLoader()).loadClass(ONLOAD_TEST_CLASS_NAME), 766 new ExpectedMethod[]{ 767 new ExpectedMethod(Void.TYPE, "alpha", int.class), 768 new ExpectedMethod(int.class, "beta"), 769 new ExpectedMethod(Void.TYPE, "gamma"), 770 }); 771 } 772 redefineClass(Class<?> target, byte[] dex)773 private static native int redefineClass(Class<?> target, byte[] dex); 774 retransformClass(Class<?> target)775 private static native int retransformClass(Class<?> target); 776 setTransformationEvent(boolean enable)777 private static native void setTransformationEvent(boolean enable); 778 clearTransformations()779 private static native void clearTransformations(); 780 pushTransformationResult(String target, byte[] dexBytes)781 private static native void pushTransformationResult(String target, byte[] dexBytes); 782 setPopTransformations(boolean enable)783 private static native void setPopTransformations(boolean enable); 784 pushTransformationResult(Class<?> target, byte[] dex)785 private static void pushTransformationResult(Class<?> target, byte[] dex) { 786 pushTransformationResult(target.getName().replace('.', '/'), dex); 787 } 788 } 789