xref: /aosp_15_r20/art/tools/ahat/src/test-dump/DumpedStuff.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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