1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 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.ref.PhantomReference; 18*795d594fSAndroid Build Coastguard Worker import java.lang.ref.ReferenceQueue; 19*795d594fSAndroid Build Coastguard Worker import java.lang.ref.SoftReference; 20*795d594fSAndroid Build Coastguard Worker import java.lang.ref.WeakReference; 21*795d594fSAndroid Build Coastguard Worker import libcore.util.NativeAllocationRegistry; 22*795d594fSAndroid Build Coastguard Worker import android.graphics.Bitmap; 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker // We take a heap dump that includes a single instance of this 25*795d594fSAndroid Build Coastguard Worker // DumpedStuff class. Objects stored as fields in this class can be easily 26*795d594fSAndroid Build Coastguard Worker // found in the hprof dump by searching for the instance of the DumpedStuff 27*795d594fSAndroid Build Coastguard Worker // class and reading the desired field. 28*795d594fSAndroid Build Coastguard Worker public class DumpedStuff extends SuperDumpedStuff { allocateObjectAtKnownSite()29*795d594fSAndroid Build Coastguard Worker private void allocateObjectAtKnownSite() { 30*795d594fSAndroid Build Coastguard Worker objectAllocatedAtKnownSite = new Object(); 31*795d594fSAndroid Build Coastguard Worker allocateObjectAtKnownSubSite(); 32*795d594fSAndroid Build Coastguard Worker allocateObjectAtObfSuperSite(); 33*795d594fSAndroid Build Coastguard Worker allocateObjectAtUnObfSuperSite(); 34*795d594fSAndroid Build Coastguard Worker allocateObjectAtOverriddenSite(); 35*795d594fSAndroid Build Coastguard Worker } 36*795d594fSAndroid Build Coastguard Worker allocateObjectAtKnownSubSite()37*795d594fSAndroid Build Coastguard Worker private void allocateObjectAtKnownSubSite() { 38*795d594fSAndroid Build Coastguard Worker objectAllocatedAtKnownSubSite = new Object(); 39*795d594fSAndroid Build Coastguard Worker } 40*795d594fSAndroid Build Coastguard Worker allocateObjectAtOverriddenSite()41*795d594fSAndroid Build Coastguard Worker public void allocateObjectAtOverriddenSite() { 42*795d594fSAndroid Build Coastguard Worker objectAllocatedAtOverriddenSite = new Object(); 43*795d594fSAndroid Build Coastguard Worker } 44*795d594fSAndroid Build Coastguard Worker DumpedStuff(boolean baseline)45*795d594fSAndroid Build Coastguard Worker DumpedStuff(boolean baseline) { 46*795d594fSAndroid Build Coastguard Worker allocateObjectAtKnownSite(); 47*795d594fSAndroid Build Coastguard Worker 48*795d594fSAndroid Build Coastguard Worker int n = baseline ? 400000 : 1000000; 49*795d594fSAndroid Build Coastguard Worker bigArray = new byte[n]; 50*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < n; i++) { 51*795d594fSAndroid Build Coastguard Worker bigArray[i] = (byte)((i * i) & 0xFF); 52*795d594fSAndroid Build Coastguard Worker } 53*795d594fSAndroid Build Coastguard Worker 54*795d594fSAndroid Build Coastguard Worker // 50000, 0xABCDABCD, and 0xBCDABCDA are arbitrary values. 55*795d594fSAndroid Build Coastguard Worker NativeAllocationRegistry registry = 56*795d594fSAndroid Build Coastguard Worker new NativeAllocationRegistry(Main.class.getClassLoader(), getNoopFreeFunction(), 50000); 57*795d594fSAndroid Build Coastguard Worker registry.registerNativeAllocation(anObject, 0xABCDABCD); 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker { 60*795d594fSAndroid Build Coastguard Worker aCleanerThunk = registry.registerNativeAllocation(aCleanedObject, 0xBCDABCDA); 61*795d594fSAndroid Build Coastguard Worker aCleanerThunk.run(); 62*795d594fSAndroid Build Coastguard Worker } 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker { 65*795d594fSAndroid Build Coastguard Worker Object object = new Object(); 66*795d594fSAndroid Build Coastguard Worker aLongStrongPathToSamplePathObject = new Reference(new Reference(new Reference(object))); 67*795d594fSAndroid Build Coastguard Worker aShortWeakPathToSamplePathObject = new WeakReference(new Reference(object)); 68*795d594fSAndroid Build Coastguard Worker } 69*795d594fSAndroid Build Coastguard Worker 70*795d594fSAndroid Build Coastguard Worker addedObject = baseline ? null : new AddedObject(); 71*795d594fSAndroid Build Coastguard Worker removedObject = baseline ? new RemovedObject() : null; 72*795d594fSAndroid Build Coastguard Worker modifiedObject = new ModifiedObject(); 73*795d594fSAndroid Build Coastguard Worker modifiedObject.value = baseline ? 5 : 8; 74*795d594fSAndroid Build Coastguard Worker modifiedObject.modifiedRefField = baseline ? "A1" : "A2"; 75*795d594fSAndroid Build Coastguard Worker modifiedObject.unmodifiedRefField = "B"; 76*795d594fSAndroid Build Coastguard Worker modifiedStaticField = baseline ? "C1" : "C2"; 77*795d594fSAndroid Build Coastguard Worker modifiedArray = baseline ? new int[]{0, 1, 2, 3} : new int[]{3, 1, 2, 0}; 78*795d594fSAndroid Build Coastguard Worker 79*795d594fSAndroid Build Coastguard Worker // Deep matching dominator trees shouldn't smash the stack when we try 80*795d594fSAndroid Build Coastguard Worker // to diff them. Make some deep dominator trees to help test it. 81*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 10000; i++) { 82*795d594fSAndroid Build Coastguard Worker StackSmasher smasher = new StackSmasher(); 83*795d594fSAndroid Build Coastguard Worker smasher.child = stackSmasher; 84*795d594fSAndroid Build Coastguard Worker stackSmasher = smasher; 85*795d594fSAndroid Build Coastguard Worker 86*795d594fSAndroid Build Coastguard Worker if (!baseline) { 87*795d594fSAndroid Build Coastguard Worker smasher = new StackSmasher(); 88*795d594fSAndroid Build Coastguard Worker smasher.child = stackSmasherAdded; 89*795d594fSAndroid Build Coastguard Worker stackSmasherAdded = smasher; 90*795d594fSAndroid Build Coastguard Worker } 91*795d594fSAndroid Build Coastguard Worker } 92*795d594fSAndroid Build Coastguard Worker 93*795d594fSAndroid Build Coastguard Worker gcPathArray[2].right.left = gcPathArray[2].left.right; 94*795d594fSAndroid Build Coastguard Worker 95*795d594fSAndroid Build Coastguard Worker bitmapOne = new Bitmap(100, 200, 0xDEADBEEF, bigArray); 96*795d594fSAndroid Build Coastguard Worker bitmapTwo = new Bitmap(100, 200, 0xBEEFDEAD, bigArray); 97*795d594fSAndroid Build Coastguard Worker } 98*795d594fSAndroid Build Coastguard Worker 99*795d594fSAndroid Build Coastguard Worker public static class ObjectTree { 100*795d594fSAndroid Build Coastguard Worker public ObjectTree left; 101*795d594fSAndroid Build Coastguard Worker public ObjectTree right; 102*795d594fSAndroid Build Coastguard Worker ObjectTree(ObjectTree left, ObjectTree right)103*795d594fSAndroid Build Coastguard Worker public ObjectTree(ObjectTree left, ObjectTree right) { 104*795d594fSAndroid Build Coastguard Worker this.left = left; 105*795d594fSAndroid Build Coastguard Worker this.right = right; 106*795d594fSAndroid Build Coastguard Worker } 107*795d594fSAndroid Build Coastguard Worker } 108*795d594fSAndroid Build Coastguard Worker 109*795d594fSAndroid Build Coastguard Worker public static class AddedObject { 110*795d594fSAndroid Build Coastguard Worker } 111*795d594fSAndroid Build Coastguard Worker 112*795d594fSAndroid Build Coastguard Worker public static class RemovedObject { 113*795d594fSAndroid Build Coastguard Worker } 114*795d594fSAndroid Build Coastguard Worker 115*795d594fSAndroid Build Coastguard Worker public static class UnchangedObject { 116*795d594fSAndroid Build Coastguard Worker } 117*795d594fSAndroid Build Coastguard Worker 118*795d594fSAndroid Build Coastguard Worker public static class ModifiedObject { 119*795d594fSAndroid Build Coastguard Worker public int value; 120*795d594fSAndroid Build Coastguard Worker public String modifiedRefField; 121*795d594fSAndroid Build Coastguard Worker public String unmodifiedRefField; 122*795d594fSAndroid Build Coastguard Worker } 123*795d594fSAndroid Build Coastguard Worker 124*795d594fSAndroid Build Coastguard Worker public static class StackSmasher { 125*795d594fSAndroid Build Coastguard Worker public StackSmasher child; 126*795d594fSAndroid Build Coastguard Worker } 127*795d594fSAndroid Build Coastguard Worker 128*795d594fSAndroid Build Coastguard Worker public static class Reference { 129*795d594fSAndroid Build Coastguard Worker public Object referent; 130*795d594fSAndroid Build Coastguard Worker Reference(Object referent)131*795d594fSAndroid Build Coastguard Worker public Reference(Object referent) { 132*795d594fSAndroid Build Coastguard Worker this.referent = referent; 133*795d594fSAndroid Build Coastguard Worker } 134*795d594fSAndroid Build Coastguard Worker } 135*795d594fSAndroid Build Coastguard Worker 136*795d594fSAndroid Build Coastguard Worker public interface IDumpedManager { 137*795d594fSAndroid Build Coastguard Worker public static class Stub extends android.os.Binder implements IDumpedManager { 138*795d594fSAndroid Build Coastguard Worker private static final java.lang.String DESCRIPTOR = "DumpedStuff$IDumpedManager"; Stub()139*795d594fSAndroid Build Coastguard Worker public Stub() { 140*795d594fSAndroid Build Coastguard Worker super(DESCRIPTOR); 141*795d594fSAndroid Build Coastguard Worker } 142*795d594fSAndroid Build Coastguard Worker public static class Proxy implements IDumpedManager { 143*795d594fSAndroid Build Coastguard Worker android.os.IBinder mRemote; Proxy(android.os.IBinder binderProxy)144*795d594fSAndroid Build Coastguard Worker Proxy(android.os.IBinder binderProxy) { 145*795d594fSAndroid Build Coastguard Worker mRemote = binderProxy; 146*795d594fSAndroid Build Coastguard Worker } 147*795d594fSAndroid Build Coastguard Worker } 148*795d594fSAndroid Build Coastguard Worker } 149*795d594fSAndroid Build Coastguard Worker } 150*795d594fSAndroid Build Coastguard Worker 151*795d594fSAndroid Build Coastguard Worker public interface IBinderInterfaceImpostor { 152*795d594fSAndroid Build Coastguard Worker public static class Stub { 153*795d594fSAndroid Build Coastguard Worker public static class Proxy implements IBinderInterfaceImpostor { 154*795d594fSAndroid Build Coastguard Worker android.os.IBinder mFakeRemote = new android.os.BinderProxy(); Proxy(android.os.IBinder binderProxy)155*795d594fSAndroid Build Coastguard Worker Proxy(android.os.IBinder binderProxy) { 156*795d594fSAndroid Build Coastguard Worker mFakeRemote = binderProxy; 157*795d594fSAndroid Build Coastguard Worker } 158*795d594fSAndroid Build Coastguard Worker } 159*795d594fSAndroid Build Coastguard Worker } 160*795d594fSAndroid Build Coastguard Worker } 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker private static class BinderProxyCarrier { 163*795d594fSAndroid Build Coastguard Worker android.os.IBinder mRemote; BinderProxyCarrier(android.os.IBinder binderProxy)164*795d594fSAndroid Build Coastguard Worker BinderProxyCarrier(android.os.IBinder binderProxy) { 165*795d594fSAndroid Build Coastguard Worker mRemote = binderProxy; 166*795d594fSAndroid Build Coastguard Worker } 167*795d594fSAndroid Build Coastguard Worker } 168*795d594fSAndroid Build Coastguard Worker 169*795d594fSAndroid Build Coastguard Worker private static class BinderService extends IDumpedManager.Stub { 170*795d594fSAndroid Build Coastguard Worker // Intentionally empty 171*795d594fSAndroid Build Coastguard Worker }; 172*795d594fSAndroid Build Coastguard Worker 173*795d594fSAndroid Build Coastguard Worker private static class FakeBinderService extends IBinderInterfaceImpostor.Stub { 174*795d594fSAndroid Build Coastguard Worker // Intentionally empty 175*795d594fSAndroid Build Coastguard Worker }; 176*795d594fSAndroid Build Coastguard Worker 177*795d594fSAndroid Build Coastguard Worker public String basicString = "hello, world"; 178*795d594fSAndroid Build Coastguard Worker public String nonAscii = "Sigma (Ʃ) is not ASCII"; 179*795d594fSAndroid Build Coastguard Worker public String embeddedZero = "embedded\0..."; // Non-ASCII for string compression purposes. 180*795d594fSAndroid Build Coastguard Worker public char[] charArray = "char thing".toCharArray(); 181*795d594fSAndroid Build Coastguard Worker public byte[] byteString = new byte[] {'h', 'i', '.', '\n', '\0', '\0', '\0'}; 182*795d594fSAndroid Build Coastguard Worker public byte[] byteNotString = new byte[] {0, 1, 2, 3, 4, 5}; 183*795d594fSAndroid Build Coastguard Worker public byte[] byteEmpty = new byte[] {}; 184*795d594fSAndroid Build Coastguard Worker public String nullString = null; 185*795d594fSAndroid Build Coastguard Worker public Object anObject = new Object(); 186*795d594fSAndroid Build Coastguard Worker public Object aCleanedObject = new Object(); 187*795d594fSAndroid Build Coastguard Worker public Runnable aCleanerThunk; 188*795d594fSAndroid Build Coastguard Worker public Reference aReference = new Reference(anObject); 189*795d594fSAndroid Build Coastguard Worker public ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>(); 190*795d594fSAndroid Build Coastguard Worker public PhantomReference aPhantomReference = new PhantomReference(anObject, referenceQueue); 191*795d594fSAndroid Build Coastguard Worker public WeakReference aWeakReference = new WeakReference(anObject, referenceQueue); 192*795d594fSAndroid Build Coastguard Worker public WeakReference aNullReferentReference = new WeakReference(null, referenceQueue); 193*795d594fSAndroid Build Coastguard Worker public SoftReference aSoftReference = new SoftReference(new Object()); 194*795d594fSAndroid Build Coastguard Worker public Reference reachabilityReferenceChain; 195*795d594fSAndroid Build Coastguard Worker public byte[] bigArray; 196*795d594fSAndroid Build Coastguard Worker public Bitmap bitmapOne = null; 197*795d594fSAndroid Build Coastguard Worker public Bitmap bitmapTwo = null; 198*795d594fSAndroid Build Coastguard Worker public ObjectTree[] gcPathArray = new ObjectTree[]{null, null, 199*795d594fSAndroid Build Coastguard Worker new ObjectTree( 200*795d594fSAndroid Build Coastguard Worker new ObjectTree(null, new ObjectTree(null, null)), 201*795d594fSAndroid Build Coastguard Worker new ObjectTree(null, null)), 202*795d594fSAndroid Build Coastguard Worker null}; 203*795d594fSAndroid Build Coastguard Worker public Reference aLongStrongPathToSamplePathObject; 204*795d594fSAndroid Build Coastguard Worker public WeakReference aShortWeakPathToSamplePathObject; 205*795d594fSAndroid Build Coastguard Worker public WeakReference aWeakRefToGcRoot = new WeakReference(Main.class); 206*795d594fSAndroid Build Coastguard Worker public SoftReference aSoftChain = new SoftReference(new Reference(new Reference(new Object()))); 207*795d594fSAndroid Build Coastguard Worker public Object[] basicStringRef; 208*795d594fSAndroid Build Coastguard Worker public AddedObject addedObject; 209*795d594fSAndroid Build Coastguard Worker public UnchangedObject unchangedObject = new UnchangedObject(); 210*795d594fSAndroid Build Coastguard Worker public RemovedObject removedObject; 211*795d594fSAndroid Build Coastguard Worker public ModifiedObject modifiedObject; 212*795d594fSAndroid Build Coastguard Worker public StackSmasher stackSmasher; 213*795d594fSAndroid Build Coastguard Worker public StackSmasher stackSmasherAdded; 214*795d594fSAndroid Build Coastguard Worker public static String modifiedStaticField; 215*795d594fSAndroid Build Coastguard Worker public int[] modifiedArray; 216*795d594fSAndroid Build Coastguard Worker public Object objectAllocatedAtKnownSite; 217*795d594fSAndroid Build Coastguard Worker public Object objectAllocatedAtKnownSubSite; 218*795d594fSAndroid Build Coastguard Worker public android.os.IBinder correctBinderProxy = new android.os.BinderProxy(); 219*795d594fSAndroid Build Coastguard Worker public android.os.IBinder imposedBinderProxy = new android.os.BinderProxy(); 220*795d594fSAndroid Build Coastguard Worker public android.os.IBinder carriedBinderProxy = new android.os.BinderProxy(); 221*795d594fSAndroid Build Coastguard Worker Object correctBinderProxyObject = new IDumpedManager.Stub.Proxy(correctBinderProxy); 222*795d594fSAndroid Build Coastguard Worker Object impostorBinderProxyObject = new IBinderInterfaceImpostor.Stub.Proxy(imposedBinderProxy); 223*795d594fSAndroid Build Coastguard Worker Object carrierBinderProxyObject = new BinderProxyCarrier(carriedBinderProxy); 224*795d594fSAndroid Build Coastguard Worker 225*795d594fSAndroid Build Coastguard Worker Object binderService = new BinderService(); 226*795d594fSAndroid Build Coastguard Worker Object fakeBinderService = new FakeBinderService(); 227*795d594fSAndroid Build Coastguard Worker Object binderToken = new android.os.Binder(); 228*795d594fSAndroid Build Coastguard Worker Object namedBinderToken = new android.os.Binder("awesomeToken"); 229*795d594fSAndroid Build Coastguard Worker 230*795d594fSAndroid Build Coastguard Worker // Allocate those objects that we need to not be GC'd before taking the heap 231*795d594fSAndroid Build Coastguard Worker // dump. shouldNotGc()232*795d594fSAndroid Build Coastguard Worker public void shouldNotGc() { 233*795d594fSAndroid Build Coastguard Worker reachabilityReferenceChain = new Reference( 234*795d594fSAndroid Build Coastguard Worker new SoftReference( 235*795d594fSAndroid Build Coastguard Worker new Reference( 236*795d594fSAndroid Build Coastguard Worker new WeakReference( 237*795d594fSAndroid Build Coastguard Worker new SoftReference( 238*795d594fSAndroid Build Coastguard Worker new PhantomReference(new Object(), referenceQueue)))))); 239*795d594fSAndroid Build Coastguard Worker } 240*795d594fSAndroid Build Coastguard Worker 241*795d594fSAndroid Build Coastguard Worker static { 242*795d594fSAndroid Build Coastguard Worker System.loadLibrary("ahat-test-jni"); 243*795d594fSAndroid Build Coastguard Worker } 244*795d594fSAndroid Build Coastguard Worker getNoopFreeFunction()245*795d594fSAndroid Build Coastguard Worker private static native long getNoopFreeFunction(); 246*795d594fSAndroid Build Coastguard Worker } 247