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.nio.ByteBuffer;
21 import java.util.ArrayList;
22 import java.util.Base64;
23 import java.util.concurrent.CountDownLatch;
24 import java.util.function.Supplier;
25 import java.util.concurrent.atomic.*;
26 import java.lang.ref.*;
27 
28 public class Test2007 {
29   public static final CountDownLatch finish_latch = new CountDownLatch(1);
30   public static volatile int counter = 0;
31   public static Object theObject = null;
32   public static class Transform {
Transform()33     public Transform() { }
finalize()34     protected void finalize() throws Throwable {
35       System.out.println("Should never be called!");
36       // Do nothing.
37     }
38   }
39 
40   /**
41    * base64 encoded class/dex file for
42    * public static class Transform {
43    *   public String greeting;
44    *
45    *   public Transform() {
46    *     greeting = "Hello";
47    *   }
48    *   protected void finalize() throws Throwable {
49    *     System.out.println("Finalizing");
50    *     counter++;
51    *     finish_latch.countDown();
52    *   }
53    * }
54    */
55   private static final byte[] DEX_BYTES =
56       Base64.getDecoder()
57           .decode(
58 "ZGV4CjAzNQCC9DECxo2lTpw7FCCSqZArgZe8ab49ywRoBQAAcAAAAHhWNBIAAAAAAAAAAKQEAAAe" +
59 "AAAAcAAAAA0AAADoAAAAAgAAABwBAAAEAAAANAEAAAUAAABUAQAAAQAAAHwBAADMAwAAnAEAAAYC" +
60 "AAAOAgAAGgIAACECAAAkAgAAPgIAAE4CAAByAgAAkgIAAK4CAADFAgAA2QIAAO0CAAABAwAAGAMA" +
61 "AD8DAABOAwAAWQMAAFwDAABgAwAAbQMAAHgDAACBAwAAiwMAAJkDAACjAwAAqQMAAK4DAAC3AwAA" +
62 "vgMAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAACwAAAAwAAAANAAAADgAAABEAAAAR" +
63 "AAAADAAAAAAAAAASAAAADAAAAAACAAABAAgAGAAAAAIAAAAVAAAAAgALABcAAAAJAAYAGgAAAAEA" +
64 "AAAAAAAAAQAAABYAAAAGAAEAGwAAAAcAAAAAAAAACwAAABQAAAABAAAAAQAAAAcAAAAAAAAADwAA" +
65 "AIwEAABkBAAAAAAAAAIAAQABAAAA8gEAAAgAAABwEAMAAQAaAAIAWxAAAA4AAwABAAIAAAD4AQAA" +
66 "EwAAAGIAAwAaAQEAbiACABAAYAABANgAAAFnAAEAYgACAG4QBAAAAA4ADAAOPEsAEAAOeGlaAAAB" +
67 "AAAACAAGPGluaXQ+AApGaW5hbGl6aW5nAAVIZWxsbwABSQAYTGFydC9UZXN0MjAwNyRUcmFuc2Zv" +
68 "cm07AA5MYXJ0L1Rlc3QyMDA3OwAiTGRhbHZpay9hbm5vdGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAe" +
69 "TGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xhc3M7ABpMZGFsdmlrL2Fubm90YXRpb24vVGhyb3dz" +
70 "OwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcv" +
71 "U3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07ABVMamF2YS9sYW5nL1Rocm93YWJsZTsAJUxqYXZh" +
72 "L3V0aWwvY29uY3VycmVudC9Db3VudERvd25MYXRjaDsADVRlc3QyMDA3LmphdmEACVRyYW5zZm9y" +
73 "bQABVgACVkwAC2FjY2Vzc0ZsYWdzAAljb3VudERvd24AB2NvdW50ZXIACGZpbmFsaXplAAxmaW5p" +
74 "c2hfbGF0Y2gACGdyZWV0aW5nAARuYW1lAANvdXQAB3ByaW50bG4ABXZhbHVlAIwBfn5EOHsiY29t" +
75 "cGlsYXRpb24tbW9kZSI6ImRlYnVnIiwiaGFzLWNoZWNrc3VtcyI6ZmFsc2UsIm1pbi1hcGkiOjEs" +
76 "InNoYS0xIjoiMTI5ZWU5ZjY3NTZjMzlkZjU3ZmYwNzg1ZDI1NmIyMzc3MjY0MmI3YyIsInZlcnNp" +
77 "b24iOiIyLjAuMTAtZGV2In0AAgUBHBwBGAoCAwEcGAICBAITBAkZFxAAAQEBAAEAgYAEnAMBBLwD" +
78 "AAAAAAEAAABNBAAAAgAAAFUEAABbBAAAgAQAAAAAAAABAAAAAAAAAAEAAAB4BAAAEAAAAAAAAAAB" +
79 "AAAAAAAAAAEAAAAeAAAAcAAAAAIAAAANAAAA6AAAAAMAAAACAAAAHAEAAAQAAAAEAAAANAEAAAUA" +
80 "AAAFAAAAVAEAAAYAAAABAAAAfAEAAAEgAAACAAAAnAEAAAMgAAACAAAA8gEAAAEQAAABAAAAAAIA" +
81 "AAIgAAAeAAAABgIAAAQgAAADAAAATQQAAAAgAAABAAAAZAQAAAMQAAADAAAAdAQAAAYgAAABAAAA" +
82 "jAQAAAAQAAABAAAApAQAAA==");
83 
84 
run()85   public static void run() throws Exception {
86     Redefinition.setTestConfiguration(Redefinition.Config.COMMON_REDEFINE);
87     doTest();
88   }
89 
90   public static final class GcThread extends Thread {
91     public volatile boolean finished = false;
run()92     public void run() {
93       while (!finished) {
94         Runtime.getRuntime().gc();
95         System.runFinalization();
96       }
97     }
98   }
99 
doTest()100   public static void doTest() throws Exception {
101     // Try GC forever
102     GcThread gc_thr = new GcThread();
103     gc_thr.start();
104     // Make a transform
105     mktransform();
106     Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES);
107     theObject = null;
108     finish_latch.await();
109     System.out.println("counter: " + counter);
110     // Make sure we don't have any remaining things to finalize, eg obsolete objects or something.
111     Runtime.getRuntime().gc();
112     System.runFinalization();
113     gc_thr.finished = true;
114     gc_thr.join();
115   }
116 
117   // Make sure there is never a transform in the frame of doTest.
mktransform()118   public static void mktransform() throws Exception {
119     theObject = new Transform();
120   }
121 }
122