• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   private static class Unreachable {
178     public Object anchor;
179     public Object self;
180 
Unreachable(Object anchor)181     public Unreachable(Object anchor) {
182       this.self = this;
183       this.anchor = anchor;
184     }
185   }
186 
187   public String basicString = "hello, world";
188   public String nonAscii = "Sigma (Ʃ) is not ASCII";
189   public String embeddedZero = "embedded\0...";  // Non-ASCII for string compression purposes.
190   public char[] charArray = "char thing".toCharArray();
191   public byte[] byteString = new byte[] {'h', 'i', '.', '\n', '\0', '\0', '\0'};
192   public byte[] byteNotString = new byte[] {0, 1, 2, 3, 4, 5};
193   public byte[] byteEmpty = new byte[] {};
194   public String nullString = null;
195   public Object anObject = new Object();
196   public Object aCleanedObject = new Object();
197   public Runnable aCleanerThunk;
198   public Reference aReference = new Reference(anObject);
199   public ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
200   public PhantomReference aPhantomReference = new PhantomReference(anObject, referenceQueue);
201   public WeakReference aWeakReference = new WeakReference(anObject, referenceQueue);
202   public WeakReference aNullReferentReference = new WeakReference(null, referenceQueue);
203   public SoftReference aSoftReference = new SoftReference(new Object());
204   public Reference reachabilityReferenceChain;
205   public byte[] bigArray;
206   public Bitmap bitmapOne = null;
207   public Bitmap bitmapTwo = null;
208   public ObjectTree[] gcPathArray = new ObjectTree[]{null, null,
209     new ObjectTree(
210         new ObjectTree(null, new ObjectTree(null, null)),
211         new ObjectTree(null, null)),
212     null};
213   public Reference aLongStrongPathToSamplePathObject;
214   public WeakReference aShortWeakPathToSamplePathObject;
215   public WeakReference aWeakRefToGcRoot = new WeakReference(Main.class);
216   public SoftReference aSoftChain = new SoftReference(new Reference(new Reference(new Object())));
217   public Object[] basicStringRef;
218   public AddedObject addedObject;
219   public UnchangedObject unchangedObject = new UnchangedObject();
220   public RemovedObject removedObject;
221   public ModifiedObject modifiedObject;
222   public StackSmasher stackSmasher;
223   public StackSmasher stackSmasherAdded;
224   public static String modifiedStaticField;
225   public int[] modifiedArray;
226   public Object objectAllocatedAtKnownSite;
227   public Object objectAllocatedAtKnownSubSite;
228   public android.os.IBinder correctBinderProxy = new android.os.BinderProxy();
229   public android.os.IBinder imposedBinderProxy = new android.os.BinderProxy();
230   public android.os.IBinder carriedBinderProxy = new android.os.BinderProxy();
231   Object correctBinderProxyObject = new IDumpedManager.Stub.Proxy(correctBinderProxy);
232   Object impostorBinderProxyObject = new IBinderInterfaceImpostor.Stub.Proxy(imposedBinderProxy);
233   Object carrierBinderProxyObject = new BinderProxyCarrier(carriedBinderProxy);
234 
235   Object binderService = new BinderService();
236   Object fakeBinderService = new FakeBinderService();
237   Object binderToken = new android.os.Binder();
238   Object namedBinderToken = new android.os.Binder("awesomeToken");
239 
240   Object unreachableAnchor = new Object();
241 
242   // Allocate those objects that we need to not be GC'd before taking the heap
243   // dump.
shouldNotGc()244   public void shouldNotGc() {
245     reachabilityReferenceChain = new Reference(
246         new SoftReference(
247         new Reference(
248         new WeakReference(
249         new SoftReference(
250         new PhantomReference(new Object(), referenceQueue))))));
251 
252     new Unreachable(unreachableAnchor);
253   }
254 
255   static {
256     System.loadLibrary("ahat-test-jni");
257   }
258 
getNoopFreeFunction()259   private static native long getNoopFreeFunction();
260 }
261