xref: /aosp_15_r20/art/test/980-redefine-object/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method;
18*795d594fSAndroid Build Coastguard Worker import java.util.ArrayList;
19*795d594fSAndroid Build Coastguard Worker import java.util.Base64;
20*795d594fSAndroid Build Coastguard Worker import java.util.LinkedList;
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker public class Main {
23*795d594fSAndroid Build Coastguard Worker   /**
24*795d594fSAndroid Build Coastguard Worker    * NB This test cannot be run on the RI.
25*795d594fSAndroid Build Coastguard Worker    * TODO We should make this run on the RI.
26*795d594fSAndroid Build Coastguard Worker    */
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker   private static final String LISTENER_LOCATION =
29*795d594fSAndroid Build Coastguard Worker       System.getenv("DEX_LOCATION") + "/980-redefine-object-ex.jar";
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker   private static Method doEnableReporting;
32*795d594fSAndroid Build Coastguard Worker   private static Method doDisableReporting;
33*795d594fSAndroid Build Coastguard Worker 
DisableReporting()34*795d594fSAndroid Build Coastguard Worker   private static void DisableReporting() {
35*795d594fSAndroid Build Coastguard Worker     if (doDisableReporting == null) {
36*795d594fSAndroid Build Coastguard Worker       return;
37*795d594fSAndroid Build Coastguard Worker     }
38*795d594fSAndroid Build Coastguard Worker     try {
39*795d594fSAndroid Build Coastguard Worker       doDisableReporting.invoke(null);
40*795d594fSAndroid Build Coastguard Worker     } catch (Exception e) {
41*795d594fSAndroid Build Coastguard Worker       throw new Error("Unable to disable reporting!");
42*795d594fSAndroid Build Coastguard Worker     }
43*795d594fSAndroid Build Coastguard Worker   }
44*795d594fSAndroid Build Coastguard Worker 
EnableReporting()45*795d594fSAndroid Build Coastguard Worker   private static void EnableReporting() {
46*795d594fSAndroid Build Coastguard Worker     if (doEnableReporting == null) {
47*795d594fSAndroid Build Coastguard Worker       return;
48*795d594fSAndroid Build Coastguard Worker     }
49*795d594fSAndroid Build Coastguard Worker     try {
50*795d594fSAndroid Build Coastguard Worker       doEnableReporting.invoke(null);
51*795d594fSAndroid Build Coastguard Worker     } catch (Exception e) {
52*795d594fSAndroid Build Coastguard Worker       throw new Error("Unable to enable reporting!");
53*795d594fSAndroid Build Coastguard Worker     }
54*795d594fSAndroid Build Coastguard Worker   }
55*795d594fSAndroid Build Coastguard Worker 
main(String[] args)56*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) {
57*795d594fSAndroid Build Coastguard Worker     doTest();
58*795d594fSAndroid Build Coastguard Worker   }
59*795d594fSAndroid Build Coastguard Worker 
ensureTestWatcherInitialized()60*795d594fSAndroid Build Coastguard Worker   private static void ensureTestWatcherInitialized() {
61*795d594fSAndroid Build Coastguard Worker     try {
62*795d594fSAndroid Build Coastguard Worker       // Make sure the TestWatcher class can be found from the Object <init> function.
63*795d594fSAndroid Build Coastguard Worker       addToBootClassLoader(LISTENER_LOCATION);
64*795d594fSAndroid Build Coastguard Worker       // Load TestWatcher from the bootclassloader and make sure it is initialized.
65*795d594fSAndroid Build Coastguard Worker       Class<?> testwatcher_class = Class.forName("art.test.TestWatcher", true, null);
66*795d594fSAndroid Build Coastguard Worker       doEnableReporting = testwatcher_class.getDeclaredMethod("EnableReporting");
67*795d594fSAndroid Build Coastguard Worker       doDisableReporting = testwatcher_class.getDeclaredMethod("DisableReporting");
68*795d594fSAndroid Build Coastguard Worker     } catch (Exception e) {
69*795d594fSAndroid Build Coastguard Worker       throw new Error("Exception while making testwatcher", e);
70*795d594fSAndroid Build Coastguard Worker     }
71*795d594fSAndroid Build Coastguard Worker   }
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker   // NB This function will cause 2 objects of type "Ljava/nio/HeapCharBuffer;" and
74*795d594fSAndroid Build Coastguard Worker   // "Ljava/nio/HeapCharBuffer;" to be allocated each time it is called.
safePrintln(Object o)75*795d594fSAndroid Build Coastguard Worker   private static void safePrintln(Object o) {
76*795d594fSAndroid Build Coastguard Worker     DisableReporting();
77*795d594fSAndroid Build Coastguard Worker     System.out.println("\t" + o);
78*795d594fSAndroid Build Coastguard Worker     EnableReporting();
79*795d594fSAndroid Build Coastguard Worker   }
80*795d594fSAndroid Build Coastguard Worker 
throwFrom(int depth)81*795d594fSAndroid Build Coastguard Worker   private static void throwFrom(int depth) throws Exception {
82*795d594fSAndroid Build Coastguard Worker     if (depth <= 0) {
83*795d594fSAndroid Build Coastguard Worker       throw new Exception("Throwing the exception");
84*795d594fSAndroid Build Coastguard Worker     } else {
85*795d594fSAndroid Build Coastguard Worker       throwFrom(depth - 1);
86*795d594fSAndroid Build Coastguard Worker     }
87*795d594fSAndroid Build Coastguard Worker   }
88*795d594fSAndroid Build Coastguard Worker 
doTest()89*795d594fSAndroid Build Coastguard Worker   public static void doTest() {
90*795d594fSAndroid Build Coastguard Worker     safePrintln("Initializing and loading the TestWatcher class that will (eventually) be " +
91*795d594fSAndroid Build Coastguard Worker                 "notified of object allocations");
92*795d594fSAndroid Build Coastguard Worker     // Make sure the TestWatcher class is initialized before we do anything else.
93*795d594fSAndroid Build Coastguard Worker     ensureTestWatcherInitialized();
94*795d594fSAndroid Build Coastguard Worker     safePrintln("Allocating an j.l.Object before redefining Object class");
95*795d594fSAndroid Build Coastguard Worker     // Make sure these aren't shown.
96*795d594fSAndroid Build Coastguard Worker     Object o = new Object();
97*795d594fSAndroid Build Coastguard Worker     safePrintln("Allocating a Transform before redefining Object class");
98*795d594fSAndroid Build Coastguard Worker     Transform t = new Transform();
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker     // Redefine the Object Class.
101*795d594fSAndroid Build Coastguard Worker     safePrintln("Redefining the Object class to add a hook into the <init> method");
102*795d594fSAndroid Build Coastguard Worker     addMemoryTrackingCall(Object.class, Thread.currentThread());
103*795d594fSAndroid Build Coastguard Worker 
104*795d594fSAndroid Build Coastguard Worker     safePrintln("Allocating an j.l.Object after redefining Object class");
105*795d594fSAndroid Build Coastguard Worker     Object o2 = new Object();
106*795d594fSAndroid Build Coastguard Worker     safePrintln("Allocating a Transform after redefining Object class");
107*795d594fSAndroid Build Coastguard Worker     Transform t2 = new Transform();
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker     // This shouldn't cause the Object constructor to be run.
110*795d594fSAndroid Build Coastguard Worker     safePrintln("Allocating an int[] after redefining Object class");
111*795d594fSAndroid Build Coastguard Worker     int[] abc = new int[12];
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker     // Try adding stuff to an array list.
114*795d594fSAndroid Build Coastguard Worker     safePrintln("Allocating an array list");
115*795d594fSAndroid Build Coastguard Worker     ArrayList<Object> al = new ArrayList<>();
116*795d594fSAndroid Build Coastguard Worker     safePrintln("Adding a bunch of stuff to the array list");
117*795d594fSAndroid Build Coastguard Worker     al.add(new Object());
118*795d594fSAndroid Build Coastguard Worker     al.add(new Object());
119*795d594fSAndroid Build Coastguard Worker     al.add(o2);
120*795d594fSAndroid Build Coastguard Worker     al.add(o);
121*795d594fSAndroid Build Coastguard Worker     al.add(t);
122*795d594fSAndroid Build Coastguard Worker     al.add(t2);
123*795d594fSAndroid Build Coastguard Worker     al.add(new Transform());
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker     // Try adding stuff to a LinkedList
126*795d594fSAndroid Build Coastguard Worker     safePrintln("Allocating a linked list");
127*795d594fSAndroid Build Coastguard Worker     LinkedList<Object> ll = new LinkedList<>();
128*795d594fSAndroid Build Coastguard Worker     safePrintln("Adding a bunch of stuff to the linked list");
129*795d594fSAndroid Build Coastguard Worker     ll.add(new Object());
130*795d594fSAndroid Build Coastguard Worker     ll.add(new Object());
131*795d594fSAndroid Build Coastguard Worker     ll.add(o2);
132*795d594fSAndroid Build Coastguard Worker     ll.add(o);
133*795d594fSAndroid Build Coastguard Worker     ll.add(t);
134*795d594fSAndroid Build Coastguard Worker     ll.add(t2);
135*795d594fSAndroid Build Coastguard Worker     ll.add(new Transform());
136*795d594fSAndroid Build Coastguard Worker 
137*795d594fSAndroid Build Coastguard Worker     // Try making an exception.
138*795d594fSAndroid Build Coastguard Worker     safePrintln("Throwing from down 4 stack frames");
139*795d594fSAndroid Build Coastguard Worker     try {
140*795d594fSAndroid Build Coastguard Worker       throwFrom(4);
141*795d594fSAndroid Build Coastguard Worker     } catch (Exception e) {
142*795d594fSAndroid Build Coastguard Worker       safePrintln("Exception caught.");
143*795d594fSAndroid Build Coastguard Worker     }
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker     safePrintln("Finishing test!");
146*795d594fSAndroid Build Coastguard Worker   }
147*795d594fSAndroid Build Coastguard Worker 
148*795d594fSAndroid Build Coastguard Worker   // This is from 929-search/search.cc
addToBootClassLoader(String s)149*795d594fSAndroid Build Coastguard Worker   private static native void addToBootClassLoader(String s);
150*795d594fSAndroid Build Coastguard Worker   // This is from 980-redefine-object/redef_object.cc
151*795d594fSAndroid Build Coastguard Worker   // It will add a call to Lart/test/TestWatcher;->NotifyConstructed()V in the Object <init>()V
152*795d594fSAndroid Build Coastguard Worker   // function.
addMemoryTrackingCall(Class c, Thread thr)153*795d594fSAndroid Build Coastguard Worker   private static native void addMemoryTrackingCall(Class c, Thread thr);
154*795d594fSAndroid Build Coastguard Worker }
155