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