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