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