• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 package art;
18 
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Random;
22 
23 public class Test906 {
run()24   public static void run() throws Exception {
25     doTest();
26   }
27 
28   // Number of times we will try to count the heap in various ways. If we are unlucky and end up in
29   // the middle of a GC we could incorrectly fail. This is expected to be incredibly rare so 10
30   // retries should be more than sufficient.
31   private static final int ITERATE_RETRIES = 10;
testHeapCount()32   private static void testHeapCount() throws Exception {
33     IllegalStateException lastThrow = new IllegalStateException(
34         "Failed to get consistent counts after " + ITERATE_RETRIES + " retries");
35     for (int i = 0; i < ITERATE_RETRIES; i++) {
36       try {
37         int all = iterateThroughHeapCount(0, null, Integer.MAX_VALUE);
38         int tagged = iterateThroughHeapCount(HEAP_FILTER_OUT_UNTAGGED, null, Integer.MAX_VALUE);
39         int untagged = iterateThroughHeapCount(HEAP_FILTER_OUT_TAGGED, null, Integer.MAX_VALUE);
40         int taggedClass = iterateThroughHeapCount(HEAP_FILTER_OUT_CLASS_UNTAGGED, null,
41             Integer.MAX_VALUE);
42         int untaggedClass = iterateThroughHeapCount(HEAP_FILTER_OUT_CLASS_TAGGED, null,
43             Integer.MAX_VALUE);
44 
45         if (all != tagged + untagged) {
46           throw new IllegalStateException("Instances: " + all + " != " + tagged + " + " + untagged);
47         }
48         if (all != taggedClass + untaggedClass) {
49           throw new IllegalStateException("By class: " + all + " != " + taggedClass + " + " +
50               untaggedClass);
51         }
52         if (tagged != 6) {
53           throw new IllegalStateException(tagged + " tagged objects");
54         }
55         if (taggedClass != 2) {
56           throw new IllegalStateException(tagged + " objects with tagged class");
57         }
58         if (all == tagged) {
59           throw new IllegalStateException("All objects tagged");
60         }
61         if (all == taggedClass) {
62           throw new IllegalStateException("All objects have tagged class");
63         }
64         // Everything worked!
65         return;
66       } catch (IllegalStateException e) {
67         lastThrow.addSuppressed(e);
68       }
69     }
70     throw lastThrow;
71   }
72 
GenTs(Class<?> k)73   private static Object[] GenTs(Class<?> k) throws Exception {
74     Object[] ret = new Object[new Random().nextInt(100) + 10];
75     for (int i = 0; i < ret.length; i++) {
76       ret[i] = k.newInstance();
77     }
78     return ret;
79   }
80 
checkEq(int a, int b)81   private static void checkEq(int a, int b) {
82     if (a != b) {
83       Error e = new Error("Failed: Expected equal " + a + " and " + b);
84       System.out.println(e);
85       e.printStackTrace(System.out);
86     }
87   }
88 
89   public static class Foo {}
90   public static class Bar extends Foo {}
91   public static class Baz extends Bar {}
92   public static class Alpha extends Bar {}
93   public static class MISSING extends Baz {}
94   public interface Iface {}
95   public static class Beta implements Iface {}
96   public static class Gamma implements Iface {}
97   public static class Delta extends Beta {}
testIterateOverInstances()98   private static void testIterateOverInstances() throws Exception {
99     Object[] foos = GenTs(Foo.class);
100     Object[] bars = GenTs(Bar.class);
101     Object[] bazs = GenTs(Baz.class);
102     Object[] alphas = GenTs(Alpha.class);
103     Object[] betas = GenTs(Beta.class);
104     Object[] gammas = GenTs(Gamma.class);
105     Object[] deltas = GenTs(Delta.class);
106     checkEq(0, iterateOverInstancesCount(MISSING.class));
107     checkEq(alphas.length, iterateOverInstancesCount(Alpha.class));
108     checkEq(bazs.length, iterateOverInstancesCount(Baz.class));
109     checkEq(bazs.length + alphas.length + bars.length, iterateOverInstancesCount(Bar.class));
110     checkEq(bazs.length + alphas.length + bars.length + foos.length,
111         iterateOverInstancesCount(Foo.class));
112     checkEq(betas.length + gammas.length + deltas.length,
113         iterateOverInstancesCount(Iface.class));
114   }
115 
doTest()116   public static void doTest() throws Exception {
117     A a = new A();
118     B b = new B();
119     B b2 = new B();
120     C c = new C();
121     A[] aArray = new A[5];
122     String s = "Hello World";
123 
124     setTag(a, 1);
125     setTag(b, 2);
126     setTag(b2, 3);
127     setTag(aArray, 4);
128     setTag(s, 5);
129     setTag(B.class, 100);
130 
131     testHeapCount();
132 
133     testIterateOverInstances();
134 
135     long classTags[] = new long[100];
136     long sizes[] = new long[100];
137     long tags[] = new long[100];
138     int lengths[] = new int[100];
139 
140     int n = iterateThroughHeapData(HEAP_FILTER_OUT_UNTAGGED, null, classTags, sizes, tags, lengths);
141     System.out.println(sort(n, classTags, sizes, tags, lengths));
142 
143     iterateThroughHeapAdd(HEAP_FILTER_OUT_UNTAGGED, null);
144     n = iterateThroughHeapData(HEAP_FILTER_OUT_UNTAGGED, null, classTags, sizes, tags, lengths);
145     System.out.println(sort(n, classTags, sizes, tags, lengths));
146 
147     System.out.println(iterateThroughHeapString(getTag(s)));
148     System.out.println(getTag(s));
149 
150     boolean[] zArray = new boolean[] { false, true };
151     setTag(zArray, 1);
152     System.out.println(iterateThroughHeapPrimitiveArray(getTag(zArray)));
153     System.out.println(getTag(zArray));
154 
155     byte[] bArray = new byte[] { 1, 2, 3 };
156     setTag(bArray, 1);
157     System.out.println(iterateThroughHeapPrimitiveArray(getTag(bArray)));
158     System.out.println(getTag(bArray));
159 
160     char[] cArray = new char[] { 'A', 'Z' };
161     setTag(cArray, 1);
162     System.out.println(iterateThroughHeapPrimitiveArray(getTag(cArray)));
163     System.out.println(getTag(cArray));
164 
165     short[] sArray = new short[] { 1, 2, 3 };
166     setTag(sArray, 1);
167     System.out.println(iterateThroughHeapPrimitiveArray(getTag(sArray)));
168     System.out.println(getTag(sArray));
169 
170     int[] iArray = new int[] { 1, 2, 3 };
171     setTag(iArray, 1);
172     System.out.println(iterateThroughHeapPrimitiveArray(getTag(iArray)));
173     System.out.println(getTag(iArray));
174 
175     float[] fArray = new float[] { 0.0f, 1.0f };
176     setTag(fArray, 1);
177     System.out.println(iterateThroughHeapPrimitiveArray(getTag(fArray)));
178     System.out.println(getTag(fArray));
179 
180     long[] lArray = new long[] { 1, 2, 3 };
181     setTag(lArray, 1);
182     System.out.println(iterateThroughHeapPrimitiveArray(getTag(lArray)));
183     System.out.println(getTag(lArray));
184 
185     double[] dArray = new double[] { 0.0, 1.0 };
186     setTag(dArray, 1);
187     System.out.println(iterateThroughHeapPrimitiveArray(getTag(dArray)));
188     System.out.println(getTag(dArray));
189 
190     // Force GCs to clean up dirt.
191     Runtime.getRuntime().gc();
192     Runtime.getRuntime().gc();
193 
194     doTestPrimitiveFieldsClasses();
195 
196     doTestPrimitiveFieldsIntegral();
197 
198     // Force GCs to clean up dirt.
199     Runtime.getRuntime().gc();
200     Runtime.getRuntime().gc();
201 
202     doTestPrimitiveFieldsFloat();
203 
204     // Force GCs to clean up dirt.
205     Runtime.getRuntime().gc();
206     Runtime.getRuntime().gc();
207   }
208 
doTestPrimitiveFieldsClasses()209   private static void doTestPrimitiveFieldsClasses() {
210     System.out.println("doTestPrimitiveFieldsClasses");
211     setTag(IntObject.class, 10000);
212     System.out.println(iterateThroughHeapPrimitiveFields(10000));
213     System.out.println(getTag(IntObject.class));
214     setTag(IntObject.class, 0);
215 
216     setTag(FloatObject.class, 10000);
217     System.out.println(iterateThroughHeapPrimitiveFields(10000));
218     System.out.println(getTag(FloatObject.class));
219     setTag(FloatObject.class, 0);
220 
221     boolean correctHeapValue = false;
222     setTag(Inf1.class, 10000);
223     String heapTrace = iterateThroughHeapPrimitiveFields(10000);
224 
225     if (!checkInitialized(Inf1.class)) {
226       correctHeapValue = heapTrace.equals("10000@0 (static, int, index=0) 0000000000000000");
227     } else {
228       correctHeapValue = heapTrace.equals("10000@0 (static, int, index=0) 0000000000000001");
229     }
230 
231     if (!correctHeapValue)
232       System.out.println("Heap Trace for Inf1 is not as expected:\n" + heapTrace);
233 
234     System.out.println(getTag(Inf1.class));
235     setTag(Inf1.class, 0);
236 
237     setTag(Inf2.class, 10000);
238     heapTrace = iterateThroughHeapPrimitiveFields(10000);
239 
240     if (!checkInitialized(Inf2.class)) {
241       correctHeapValue = heapTrace.equals("10000@0 (static, int, index=1) 0000000000000000");
242     } else {
243       correctHeapValue = heapTrace.equals("10000@0 (static, int, index=1) 0000000000000001");
244     }
245 
246     if (!correctHeapValue)
247       System.out.println("Heap Trace for Inf2 is not as expected:\n" + heapTrace);
248     System.out.println(getTag(Inf2.class));
249 
250     setTag(Inf2.class, 0);
251   }
252 
doTestPrimitiveFieldsIntegral()253   private static void doTestPrimitiveFieldsIntegral() {
254     System.out.println("doTestPrimitiveFieldsIntegral");
255     IntObject intObject = new IntObject();
256     setTag(intObject, 10000);
257     System.out.println(iterateThroughHeapPrimitiveFields(10000));
258     System.out.println(getTag(intObject));
259   }
260 
doTestPrimitiveFieldsFloat()261   private static void doTestPrimitiveFieldsFloat() {
262     System.out.println("doTestPrimitiveFieldsFloat");
263     FloatObject floatObject = new FloatObject();
264     setTag(floatObject, 10000);
265     System.out.println(iterateThroughHeapPrimitiveFields(10000));
266     System.out.println(getTag(floatObject));
267   }
268 
269   static class A {
270   }
271 
272   static class B {
273   }
274 
275   static class C {
276   }
277 
278   static class HeapElem implements Comparable<HeapElem> {
279     long classTag;
280     long size;
281     long tag;
282     int length;
283 
compareTo(HeapElem other)284     public int compareTo(HeapElem other) {
285       if (tag != other.tag) {
286         return Long.compare(tag, other.tag);
287       }
288       if (classTag != other.classTag) {
289         return Long.compare(classTag, other.classTag);
290       }
291       if (size != other.size) {
292         return Long.compare(size, other.size);
293       }
294       return Integer.compare(length, other.length);
295     }
296 
toString()297     public String toString() {
298       return "{tag=" + tag + ", class-tag=" + classTag + ", size=" +
299           (tag >= 100 ? "<class>" : size)  // Class size is dependent on 32-bit vs 64-bit,
300                                            // so strip it.
301           + ", length=" + length + "}";
302     }
303   }
304 
sort(int n, long classTags[], long sizes[], long tags[], int lengths[])305   private static ArrayList<HeapElem> sort(int n, long classTags[], long sizes[], long tags[],
306       int lengths[]) {
307     ArrayList<HeapElem> ret = new ArrayList<HeapElem>(n);
308     for (int i = 0; i < n; i++) {
309       HeapElem elem = new HeapElem();
310       elem.classTag = classTags[i];
311       elem.size = sizes[i];
312       elem.tag = tags[i];
313       elem.length = lengths[i];
314       ret.add(elem);
315     }
316     Collections.sort(ret);
317     return ret;
318   }
319 
320   private static interface Inf1 {
321     public final static int A = 1;
322   }
323 
324   private static interface Inf2 extends Inf1 {
325     public final static int B = 1;
326   }
327 
328   private static class IntObject implements Inf1 {
329     byte b = (byte)1;
330     char c= 'a';
331     short s = (short)2;
332     int i = 3;
333     long l = 4;
334     Object o = new Object();
335     static int sI = 5;
336   }
337 
338   private static class FloatObject extends IntObject implements Inf2 {
339     float f = 1.23f;
340     double d = 1.23;
341     Object p = new Object();
342     static int sI = 6;
343   }
344 
345   private final static int HEAP_FILTER_OUT_TAGGED = 0x4;
346   private final static int HEAP_FILTER_OUT_UNTAGGED = 0x8;
347   private final static int HEAP_FILTER_OUT_CLASS_TAGGED = 0x10;
348   private final static int HEAP_FILTER_OUT_CLASS_UNTAGGED = 0x20;
349 
setTag(Object o, long tag)350   private static void setTag(Object o, long tag) {
351     Main.setTag(o, tag);
352   }
getTag(Object o)353   private static long getTag(Object o) {
354     return Main.getTag(o);
355   }
356 
iterateOverInstancesCount(Class<?> klass)357   private static native int iterateOverInstancesCount(Class<?> klass);
358 
checkInitialized(Class<?> klass)359   private static native boolean checkInitialized(Class<?> klass);
iterateThroughHeapCount(int heapFilter, Class<?> klassFilter, int stopAfter)360   private static native int iterateThroughHeapCount(int heapFilter,
361       Class<?> klassFilter, int stopAfter);
iterateThroughHeapData(int heapFilter, Class<?> klassFilter, long classTags[], long sizes[], long tags[], int lengths[])362   private static native int iterateThroughHeapData(int heapFilter,
363       Class<?> klassFilter, long classTags[], long sizes[], long tags[], int lengths[]);
iterateThroughHeapAdd(int heapFilter, Class<?> klassFilter)364   private static native int iterateThroughHeapAdd(int heapFilter,
365       Class<?> klassFilter);
iterateThroughHeapString(long tag)366   private static native String iterateThroughHeapString(long tag);
iterateThroughHeapPrimitiveArray(long tag)367   private static native String iterateThroughHeapPrimitiveArray(long tag);
iterateThroughHeapPrimitiveFields(long tag)368   private static native String iterateThroughHeapPrimitiveFields(long tag);
369 }
370