1 /*
2  * Copyright (C) 2019 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 dalvik.system.InMemoryDexClassLoader;
20 import java.lang.ref.*;
21 import java.nio.ByteBuffer;
22 import java.util.Base64;
23 import java.util.concurrent.atomic.*;
24 
25 public class Test2009 {
26   public static class Transform {
Transform()27     public Transform() {}
28   }
29   /*
30    * base64 encoded class/dex file for
31    *
32    * package art;
33    * public class Transform {
34    *   public Transform() { }
35    * }
36    */
37   private static final byte[] DEX_BYTES_INITIAL =
38       Base64.getDecoder()
39           .decode(
40               "ZGV4CjAzNQBMYVKB9B8EiEj/K5pUWVbEqHPGshupr2RkAgAAcAAAAHhWNBIAAAAAAAAAANABAAAG"
41                   + "AAAAcAAAAAMAAACIAAAAAQAAAJQAAAAAAAAAAAAAAAIAAACgAAAAAQAAALAAAACUAQAA0AAAAPAA"
42                   + "AAD4AAAACQEAAB0BAAAtAQAAMAEAAAEAAAACAAAABAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAQAA"
43                   + "AAAAAAAAAAAAAQAAAAEAAAAAAAAAAwAAAAAAAAC/AQAAAAAAAAEAAQABAAAA6AAAAAQAAABwEAEA"
44                   + "AAAOAAMADjwAAAAABjxpbml0PgAPTGFydC9UcmFuc2Zvcm07ABJMamF2YS9sYW5nL09iamVjdDsA"
45                   + "DlRyYW5zZm9ybS5qYXZhAAFWAIwBfn5EOHsiY29tcGlsYXRpb24tbW9kZSI6ImRlYnVnIiwiaGFz"
46                   + "LWNoZWNrc3VtcyI6ZmFsc2UsIm1pbi1hcGkiOjEsInNoYS0xIjoiZDFkNTFjMWNiM2U4NWFhMzBl"
47                   + "MDBhNjgyMmNjYTgzYmJlMWRmZTk0NSIsInZlcnNpb24iOiIyLjAuMTMtZGV2In0AAAABAACBgATQ"
48                   + "AQAAAAAAAAAMAAAAAAAAAAEAAAAAAAAAAQAAAAYAAABwAAAAAgAAAAMAAACIAAAAAwAAAAEAAACU"
49                   + "AAAABQAAAAIAAACgAAAABgAAAAEAAACwAAAAASAAAAEAAADQAAAAAyAAAAEAAADoAAAAAiAAAAYA"
50                   + "AADwAAAAACAAAAEAAAC/AQAAAxAAAAEAAADMAQAAABAAAAEAAADQAQAA");
51 
52   /*
53    * base64 encoded class/dex file for
54    * package art;
55    * public static class Transform {
56    *   public String greeting;
57    *   public static String static_greeting;
58    *
59    *   public Transform() {
60    *     greeting = "Hello";
61    *   }
62    *   public static String getGreetingStatic() {
63    *     static_greeting = "static-meth";
64    *     return static_greeting;
65    *   }
66    *   public String getGreeting() { greeting = "meth"; return greeting; }
67    * }
68    */
69   private static final byte[] DEX_BYTES =
70       Base64.getDecoder()
71           .decode(
72               "ZGV4CjAzNQB6kDahLt0Aoqc///gYs0Vgd/hpukfKc5mEAwAAcAAAAHhWNBIAAAAAAAAAAOQCAAAP"
73                   + "AAAAcAAAAAQAAACsAAAAAgAAALwAAAACAAAA1AAAAAQAAADkAAAAAQAAAAQBAABgAgAAJAEAAIwB"
74                   + "AACUAQAAmwEAAJ4BAACvAQAAwwEAANcBAADnAQAA6gEAAPcBAAAKAgAAFAIAABoCAAAnAgAAOAIA"
75                   + "AAMAAAAEAAAABQAAAAcAAAACAAAAAgAAAAAAAAAHAAAAAwAAAAAAAAAAAAIACgAAAAAAAgANAAAA"
76                   + "AAABAAAAAAAAAAAACAAAAAAAAAAJAAAAAQABAAAAAAAAAAAAAQAAAAEAAAAAAAAABgAAAAAAAADH"
77                   + "AgAAAAAAAAIAAQAAAAAAhgEAAAUAAAAaAAsAWxAAABEAAAABAAAAAAAAAIIBAAAFAAAAGgAMAGkA"
78                   + "AQARAAAAAgABAAEAAAB8AQAACAAAAHAQAwABABoAAQBbEAAADgAGAA48SwAJAA4ACgAOAAAABjxp"
79                   + "bml0PgAFSGVsbG8AAUwAD0xhcnQvVHJhbnNmb3JtOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2"
80                   + "YS9sYW5nL1N0cmluZzsADlRyYW5zZm9ybS5qYXZhAAFWAAtnZXRHcmVldGluZwARZ2V0R3JlZXRp"
81                   + "bmdTdGF0aWMACGdyZWV0aW5nAARtZXRoAAtzdGF0aWMtbWV0aAAPc3RhdGljX2dyZWV0aW5nAIwB"
82                   + "fn5EOHsiY29tcGlsYXRpb24tbW9kZSI6ImRlYnVnIiwiaGFzLWNoZWNrc3VtcyI6ZmFsc2UsIm1p"
83                   + "bi1hcGkiOjEsInNoYS0xIjoiZDFkNTFjMWNiM2U4NWFhMzBlMDBhNjgyMmNjYTgzYmJlMWRmZTk0"
84                   + "NSIsInZlcnNpb24iOiIyLjAuMTMtZGV2In0AAQECAQEJAAEAgYAE3AICCcACAQGkAgAAAAAAAAAN"
85                   + "AAAAAAAAAAEAAAAAAAAAAQAAAA8AAABwAAAAAgAAAAQAAACsAAAAAwAAAAIAAAC8AAAABAAAAAIA"
86                   + "AADUAAAABQAAAAQAAADkAAAABgAAAAEAAAAEAQAAASAAAAMAAAAkAQAAAyAAAAMAAAB8AQAAAiAA"
87                   + "AA8AAACMAQAAACAAAAEAAADHAgAAAxAAAAEAAADgAgAAABAAAAEAAADkAgAA");
88 
run()89   public static void run() throws Exception {
90     Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE);
91     doTest();
92   }
93 
MakeClass()94   public static Class<?> MakeClass() throws Exception {
95     return new InMemoryDexClassLoader(
96             ByteBuffer.wrap(DEX_BYTES_INITIAL), Test2009.class.getClassLoader())
97         .loadClass("art.Transform");
98   }
99 
doTest()100   public static void doTest() throws Exception {
101     // Make a transform
102     Class<?> ifields = MakeClass();
103     String res =
104         NativeLocalGetIField(
105             ifields.newInstance(),
106             () -> {
107               System.out.println("Doing redefinition for instance field");
108               Redefinition.doCommonStructuralClassRedefinition(ifields, DEX_BYTES);
109             });
110     System.out.println("Result was " + res);
111     Class<?> sfields = MakeClass();
112     res =
113         NativeLocalGetSField(
114             sfields.newInstance(),
115             () -> {
116               System.out.println("Doing redefinition for static field");
117               Redefinition.doCommonStructuralClassRedefinition(sfields, DEX_BYTES);
118             });
119     System.out.println("Result was " + res);
120     Class<?> imeths = MakeClass();
121     res =
122         NativeLocalCallVirtual(
123             imeths.newInstance(),
124             () -> {
125               System.out.println("Doing redefinition for instance method");
126               Redefinition.doCommonStructuralClassRedefinition(imeths, DEX_BYTES);
127             });
128     System.out.println("Result was " + res);
129     Class<?> smeths = MakeClass();
130     res =
131         NativeLocalCallStatic(
132             smeths.newInstance(),
133             () -> {
134               System.out.println("Doing redefinition for static method");
135               Redefinition.doCommonStructuralClassRedefinition(smeths, DEX_BYTES);
136             });
137     System.out.println("Result was " + res);
138   }
139 
NativeLocalCallVirtual(Object t, Runnable thnk)140   public static native String NativeLocalCallVirtual(Object t, Runnable thnk);
141 
NativeLocalCallStatic(Object t, Runnable thnk)142   public static native String NativeLocalCallStatic(Object t, Runnable thnk);
143 
NativeLocalGetIField(Object t, Runnable thnk)144   public static native String NativeLocalGetIField(Object t, Runnable thnk);
145 
NativeLocalGetSField(Object t, Runnable thnk)146   public static native String NativeLocalGetSField(Object t, Runnable thnk);
147 }
148