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