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.Arrays; 21 22 public class Test904 { run()23 public static void run() throws Exception { 24 // Use a list to ensure objects must be allocated. 25 ArrayList<Object> l = new ArrayList<>(100); 26 27 prefetchClassNames(); 28 29 doTest(l); 30 } 31 32 // Pre-resolve class names so the strings don't have to be allocated as a side effect of 33 // callback printing. prefetchClassNames()34 private static void prefetchClassNames() { 35 Object.class.getName(); 36 Integer.class.getName(); 37 Float.class.getName(); 38 Short.class.getName(); 39 Byte.class.getName(); 40 Double.class.getName(); 41 } 42 doTest(ArrayList<Object> l)43 public static void doTest(ArrayList<Object> l) throws Exception { 44 // Disable the global registration from OnLoad, to get into a known state. 45 enableAllocationTracking(null, false); 46 47 // Enable actual logging callback. 48 setupObjectAllocCallback(true); 49 50 System.out.println(Arrays.toString(getTrackingEventMessages( 51 new Thread[] { Thread.currentThread(), }))); 52 53 enableAllocationTracking(null, true); 54 55 l.add(new Object()); 56 l.add(new Integer(1)); 57 58 enableAllocationTracking(null, false); 59 60 l.add(new Float(1.0f)); 61 62 enableAllocationTracking(Thread.currentThread(), true); 63 64 l.add(new Short((short)0)); 65 66 enableAllocationTracking(Thread.currentThread(), false); 67 68 l.add(new Byte((byte)0)); 69 70 System.out.println(Arrays.toString(getTrackingEventMessages( 71 new Thread[] { Thread.currentThread(), }))); 72 System.out.println("Tracking on same thread"); 73 74 Thread test_thread = testThread(l, true, true); 75 76 l.add(new Byte((byte)0)); 77 78 System.out.println(Arrays.toString(getTrackingEventMessages( 79 new Thread[] { Thread.currentThread(), test_thread, }))); 80 System.out.println("Tracking on same thread, not disabling tracking"); 81 82 test_thread = testThread(l, true, false); 83 84 System.out.println(Arrays.toString(getTrackingEventMessages( 85 new Thread[] { Thread.currentThread(), test_thread, }))); 86 System.out.println("Tracking on different thread"); 87 88 test_thread = testThread(l, false, true); 89 90 l.add(new Byte((byte)0)); 91 92 // Disable actual logging callback and re-enable tracking, so we can keep the event enabled and 93 // check that shutdown works correctly. 94 setupObjectAllocCallback(false); 95 96 System.out.println(Arrays.toString(getTrackingEventMessages( 97 new Thread[] { Thread.currentThread(), test_thread, }))); 98 99 enableAllocationTracking(null, true); 100 } 101 testThread(final ArrayList<Object> l, final boolean sameThread, final boolean disableTracking)102 private static Thread testThread(final ArrayList<Object> l, final boolean sameThread, 103 final boolean disableTracking) throws Exception { 104 final SimpleBarrier startBarrier = new SimpleBarrier(1); 105 final SimpleBarrier trackBarrier = new SimpleBarrier(1); 106 final SimpleBarrier disableBarrier = new SimpleBarrier(1); 107 108 final Thread thisThread = Thread.currentThread(); 109 110 Thread t = new Thread() { 111 public void run() { 112 try { 113 startBarrier.dec(); 114 trackBarrier.waitFor(); 115 } catch (Exception e) { 116 e.printStackTrace(System.out); 117 System.exit(1); 118 } 119 120 l.add(new Double(0.0)); 121 122 if (disableTracking) { 123 enableAllocationTracking(sameThread ? this : thisThread, false); 124 } 125 } 126 }; 127 128 t.start(); 129 startBarrier.waitFor(); 130 enableAllocationTracking(sameThread ? t : Thread.currentThread(), true); 131 trackBarrier.dec(); 132 133 t.join(); 134 return t; 135 } 136 137 private static class SimpleBarrier { 138 int count; 139 SimpleBarrier(int i)140 public SimpleBarrier(int i) { 141 count = i; 142 } 143 dec()144 public synchronized void dec() throws Exception { 145 count--; 146 notifyAll(); 147 } 148 waitFor()149 public synchronized void waitFor() throws Exception { 150 while (count != 0) { 151 wait(); 152 } 153 } 154 } 155 setupObjectAllocCallback(boolean enable)156 private static native void setupObjectAllocCallback(boolean enable); enableAllocationTracking(Thread thread, boolean enable)157 private static native void enableAllocationTracking(Thread thread, boolean enable); getTrackingEventMessages(Thread[] threads)158 private static native String[] getTrackingEventMessages(Thread[] threads); 159 } 160