• 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 {}
testIterateOverInstances()94   private static void testIterateOverInstances() throws Exception {
95     Object[] foos = GenTs(Foo.class);
96     Object[] bars = GenTs(Bar.class);
97     Object[] bazs = GenTs(Baz.class);
98     Object[] alphas = GenTs(Alpha.class);
99     checkEq(0, iterateOverInstancesCount(MISSING.class));
100     checkEq(alphas.length, iterateOverInstancesCount(Alpha.class));
101     checkEq(bazs.length, iterateOverInstancesCount(Baz.class));
102     checkEq(bazs.length + alphas.length + bars.length, iterateOverInstancesCount(Bar.class));
103     checkEq(bazs.length + alphas.length + bars.length + foos.length,
104         iterateOverInstancesCount(Foo.class));
105   }
106 
doTest()107   public static void doTest() throws Exception {
108     A a = new A();
109     B b = new B();
110     B b2 = new B();
111     C c = new C();
112     A[] aArray = new A[5];
113     String s = "Hello World";
114 
115     setTag(a, 1);
116     setTag(b, 2);
117     setTag(b2, 3);
118     setTag(aArray, 4);
119     setTag(s, 5);
120     setTag(B.class, 100);
121 
122     testHeapCount();
123 
124     testIterateOverInstances();
125 
126     long classTags[] = new long[100];
127     long sizes[] = new long[100];
128     long tags[] = new long[100];
129     int lengths[] = new int[100];
130 
131     int n = iterateThroughHeapData(HEAP_FILTER_OUT_UNTAGGED, null, classTags, sizes, tags, lengths);
132     System.out.println(sort(n, classTags, sizes, tags, lengths));
133 
134     iterateThroughHeapAdd(HEAP_FILTER_OUT_UNTAGGED, null);
135     n = iterateThroughHeapData(HEAP_FILTER_OUT_UNTAGGED, null, classTags, sizes, tags, lengths);
136     System.out.println(sort(n, classTags, sizes, tags, lengths));
137 
138     System.out.println(iterateThroughHeapString(getTag(s)));
139     System.out.println(getTag(s));
140 
141     boolean[] zArray = new boolean[] { false, true };
142     setTag(zArray, 1);
143     System.out.println(iterateThroughHeapPrimitiveArray(getTag(zArray)));
144     System.out.println(getTag(zArray));
145 
146     byte[] bArray = new byte[] { 1, 2, 3 };
147     setTag(bArray, 1);
148     System.out.println(iterateThroughHeapPrimitiveArray(getTag(bArray)));
149     System.out.println(getTag(bArray));
150 
151     char[] cArray = new char[] { 'A', 'Z' };
152     setTag(cArray, 1);
153     System.out.println(iterateThroughHeapPrimitiveArray(getTag(cArray)));
154     System.out.println(getTag(cArray));
155 
156     short[] sArray = new short[] { 1, 2, 3 };
157     setTag(sArray, 1);
158     System.out.println(iterateThroughHeapPrimitiveArray(getTag(sArray)));
159     System.out.println(getTag(sArray));
160 
161     int[] iArray = new int[] { 1, 2, 3 };
162     setTag(iArray, 1);
163     System.out.println(iterateThroughHeapPrimitiveArray(getTag(iArray)));
164     System.out.println(getTag(iArray));
165 
166     float[] fArray = new float[] { 0.0f, 1.0f };
167     setTag(fArray, 1);
168     System.out.println(iterateThroughHeapPrimitiveArray(getTag(fArray)));
169     System.out.println(getTag(fArray));
170 
171     long[] lArray = new long[] { 1, 2, 3 };
172     setTag(lArray, 1);
173     System.out.println(iterateThroughHeapPrimitiveArray(getTag(lArray)));
174     System.out.println(getTag(lArray));
175 
176     double[] dArray = new double[] { 0.0, 1.0 };
177     setTag(dArray, 1);
178     System.out.println(iterateThroughHeapPrimitiveArray(getTag(dArray)));
179     System.out.println(getTag(dArray));
180 
181     // Force GCs to clean up dirt.
182     Runtime.getRuntime().gc();
183     Runtime.getRuntime().gc();
184 
185     doTestPrimitiveFieldsClasses();
186 
187     doTestPrimitiveFieldsIntegral();
188 
189     // Force GCs to clean up dirt.
190     Runtime.getRuntime().gc();
191     Runtime.getRuntime().gc();
192 
193     doTestPrimitiveFieldsFloat();
194 
195     // Force GCs to clean up dirt.
196     Runtime.getRuntime().gc();
197     Runtime.getRuntime().gc();
198   }
199 
doTestPrimitiveFieldsClasses()200   private static void doTestPrimitiveFieldsClasses() {
201     System.out.println("doTestPrimitiveFieldsClasses");
202     setTag(IntObject.class, 10000);
203     System.out.println(iterateThroughHeapPrimitiveFields(10000));
204     System.out.println(getTag(IntObject.class));
205     setTag(IntObject.class, 0);
206 
207     setTag(FloatObject.class, 10000);
208     System.out.println(iterateThroughHeapPrimitiveFields(10000));
209     System.out.println(getTag(FloatObject.class));
210     setTag(FloatObject.class, 0);
211 
212     boolean correctHeapValue = false;
213     setTag(Inf1.class, 10000);
214     String heapTrace = iterateThroughHeapPrimitiveFields(10000);
215 
216     if (!checkInitialized(Inf1.class)) {
217       correctHeapValue = heapTrace.equals("10000@0 (static, int, index=0) 0000000000000000");
218     } else {
219       correctHeapValue = heapTrace.equals("10000@0 (static, int, index=0) 0000000000000001");
220     }
221 
222     if (!correctHeapValue)
223       System.out.println("Heap Trace for Inf1 is not as expected:\n" + heapTrace);
224 
225     System.out.println(getTag(Inf1.class));
226     setTag(Inf1.class, 0);
227 
228     setTag(Inf2.class, 10000);
229     heapTrace = iterateThroughHeapPrimitiveFields(10000);
230 
231     if (!checkInitialized(Inf2.class)) {
232       correctHeapValue = heapTrace.equals("10000@0 (static, int, index=1) 0000000000000000");
233     } else {
234       correctHeapValue = heapTrace.equals("10000@0 (static, int, index=1) 0000000000000001");
235     }
236 
237     if (!correctHeapValue)
238       System.out.println("Heap Trace for Inf2 is not as expected:\n" + heapTrace);
239     System.out.println(getTag(Inf2.class));
240 
241     setTag(Inf2.class, 0);
242   }
243 
doTestPrimitiveFieldsIntegral()244   private static void doTestPrimitiveFieldsIntegral() {
245     System.out.println("doTestPrimitiveFieldsIntegral");
246     IntObject intObject = new IntObject();
247     setTag(intObject, 10000);
248     System.out.println(iterateThroughHeapPrimitiveFields(10000));
249     System.out.println(getTag(intObject));
250   }
251 
doTestPrimitiveFieldsFloat()252   private static void doTestPrimitiveFieldsFloat() {
253     System.out.println("doTestPrimitiveFieldsFloat");
254     FloatObject floatObject = new FloatObject();
255     setTag(floatObject, 10000);
256     System.out.println(iterateThroughHeapPrimitiveFields(10000));
257     System.out.println(getTag(floatObject));
258   }
259 
260   static class A {
261   }
262 
263   static class B {
264   }
265 
266   static class C {
267   }
268 
269   static class HeapElem implements Comparable<HeapElem> {
270     long classTag;
271     long size;
272     long tag;
273     int length;
274 
compareTo(HeapElem other)275     public int compareTo(HeapElem other) {
276       if (tag != other.tag) {
277         return Long.compare(tag, other.tag);
278       }
279       if (classTag != other.classTag) {
280         return Long.compare(classTag, other.classTag);
281       }
282       if (size != other.size) {
283         return Long.compare(size, other.size);
284       }
285       return Integer.compare(length, other.length);
286     }
287 
toString()288     public String toString() {
289       return "{tag=" + tag + ", class-tag=" + classTag + ", size=" +
290           (tag >= 100 ? "<class>" : size)  // Class size is dependent on 32-bit vs 64-bit,
291                                            // so strip it.
292           + ", length=" + length + "}";
293     }
294   }
295 
sort(int n, long classTags[], long sizes[], long tags[], int lengths[])296   private static ArrayList<HeapElem> sort(int n, long classTags[], long sizes[], long tags[],
297       int lengths[]) {
298     ArrayList<HeapElem> ret = new ArrayList<HeapElem>(n);
299     for (int i = 0; i < n; i++) {
300       HeapElem elem = new HeapElem();
301       elem.classTag = classTags[i];
302       elem.size = sizes[i];
303       elem.tag = tags[i];
304       elem.length = lengths[i];
305       ret.add(elem);
306     }
307     Collections.sort(ret);
308     return ret;
309   }
310 
311   private static interface Inf1 {
312     public final static int A = 1;
313   }
314 
315   private static interface Inf2 extends Inf1 {
316     public final static int B = 1;
317   }
318 
319   private static class IntObject implements Inf1 {
320     byte b = (byte)1;
321     char c= 'a';
322     short s = (short)2;
323     int i = 3;
324     long l = 4;
325     Object o = new Object();
326     static int sI = 5;
327   }
328 
329   private static class FloatObject extends IntObject implements Inf2 {
330     float f = 1.23f;
331     double d = 1.23;
332     Object p = new Object();
333     static int sI = 6;
334   }
335 
336   private final static int HEAP_FILTER_OUT_TAGGED = 0x4;
337   private final static int HEAP_FILTER_OUT_UNTAGGED = 0x8;
338   private final static int HEAP_FILTER_OUT_CLASS_TAGGED = 0x10;
339   private final static int HEAP_FILTER_OUT_CLASS_UNTAGGED = 0x20;
340 
setTag(Object o, long tag)341   private static void setTag(Object o, long tag) {
342     Main.setTag(o, tag);
343   }
getTag(Object o)344   private static long getTag(Object o) {
345     return Main.getTag(o);
346   }
347 
iterateOverInstancesCount(Class<?> klass)348   private static native int iterateOverInstancesCount(Class<?> klass);
349 
checkInitialized(Class<?> klass)350   private static native boolean checkInitialized(Class<?> klass);
iterateThroughHeapCount(int heapFilter, Class<?> klassFilter, int stopAfter)351   private static native int iterateThroughHeapCount(int heapFilter,
352       Class<?> klassFilter, int stopAfter);
iterateThroughHeapData(int heapFilter, Class<?> klassFilter, long classTags[], long sizes[], long tags[], int lengths[])353   private static native int iterateThroughHeapData(int heapFilter,
354       Class<?> klassFilter, long classTags[], long sizes[], long tags[], int lengths[]);
iterateThroughHeapAdd(int heapFilter, Class<?> klassFilter)355   private static native int iterateThroughHeapAdd(int heapFilter,
356       Class<?> klassFilter);
iterateThroughHeapString(long tag)357   private static native String iterateThroughHeapString(long tag);
iterateThroughHeapPrimitiveArray(long tag)358   private static native String iterateThroughHeapPrimitiveArray(long tag);
iterateThroughHeapPrimitiveFields(long tag)359   private static native String iterateThroughHeapPrimitiveFields(long tag);
360 }
361