1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 package android.jvmti.cts; 15 16 import static org.junit.Assert.assertEquals; 17 import static org.junit.Assert.assertTrue; 18 19 import java.util.ArrayList; 20 import org.junit.Before; 21 import org.junit.Test; 22 23 import art.Main; 24 25 /** 26 * Check tracking-related functionality. 27 */ 28 public class JvmtiTrackingTest extends JvmtiTestBase { 29 30 @Before setUp()31 public void setUp() throws Exception { 32 prefetchClassNames(); 33 } 34 35 // Pre-resolve class names so the strings don't have to be allocated as a side effect of 36 // callback printing. 37 @SuppressWarnings("ReturnValueIgnored") prefetchClassNames()38 private static void prefetchClassNames() { 39 Object.class.getName(); 40 Integer.class.getName(); 41 Float.class.getName(); 42 Short.class.getName(); 43 Byte.class.getName(); 44 Double.class.getName(); 45 } 46 47 private ArrayList<Object> l = new ArrayList<>(100); 48 49 @Test testTracking()50 public void testTracking() throws Exception { 51 // Disable the global registration from OnLoad, to get into a known state. 52 enableAllocationTracking(null, false); 53 54 assertEquals(null, getAndResetAllocationTrackingString()); 55 56 // Enable actual logging callback. 57 setupObjectAllocCallback(true); 58 59 enableAllocationTracking(null, true); 60 61 l.add(new Object()); 62 l.add(new Integer(1)); 63 64 enableAllocationTracking(null, false); 65 66 String trackingString = getAndResetAllocationTrackingString(); 67 String object_line = "ObjectAllocated type java.lang.Object/java.lang.Object size 8#"; 68 String integer_line = "ObjectAllocated type java.lang.Integer/java.lang.Integer size 16#"; 69 assertTrue("does not contain " + object_line, trackingString.contains(object_line)); 70 assertTrue("does not contain " + integer_line, trackingString.contains(integer_line)); 71 72 l.add(new Float(1.0f)); 73 74 assertEquals(null, getAndResetAllocationTrackingString()); 75 76 enableAllocationTracking(Thread.currentThread(), true); 77 78 l.add(new Short((short) 0)); 79 80 enableAllocationTracking(Thread.currentThread(), false); 81 82 assertEquals("ObjectAllocated type java.lang.Short/java.lang.Short size 16#", 83 getAndResetAllocationTrackingString()); 84 85 l.add(new Byte((byte) 0)); 86 87 assertEquals(null, getAndResetAllocationTrackingString()); 88 89 testThread(l, true, true); 90 91 l.add(new Byte((byte) 0)); 92 93 assertEquals("ObjectAllocated type java.lang.Double/java.lang.Double size 16#", 94 getAndResetAllocationTrackingString()); 95 96 testThread(l, true, false); 97 98 assertEquals("ObjectAllocated type java.lang.Double/java.lang.Double size 16#", 99 getAndResetAllocationTrackingString()); 100 101 System.out.println("Tracking on different thread"); 102 103 testThread(l, false, true); 104 105 l.add(new Byte((byte) 0)); 106 107 // Disable actual logging callback and re-enable tracking, so we can keep the event enabled 108 // and 109 // check that shutdown works correctly. 110 setupObjectAllocCallback(false); 111 enableAllocationTracking(null, true); 112 113 assertEquals(null, getAndResetAllocationTrackingString()); 114 } 115 testThread(final ArrayList<Object> l, final boolean sameThread, final boolean disableTracking)116 private static void testThread(final ArrayList<Object> l, final boolean sameThread, 117 final boolean disableTracking) throws Exception { 118 final SimpleBarrier startBarrier = new SimpleBarrier(1); 119 final SimpleBarrier trackBarrier = new SimpleBarrier(1); 120 121 final Thread thisThread = Thread.currentThread(); 122 123 Thread t = new Thread() { 124 @Override 125 public void run() { 126 try { 127 startBarrier.dec(); 128 trackBarrier.waitFor(); 129 } catch (Exception e) { 130 e.printStackTrace(System.out); 131 System.exit(1); 132 } 133 134 l.add(new Double(0.0)); 135 136 if (disableTracking) { 137 enableAllocationTracking(sameThread ? this : thisThread, false); 138 } 139 } 140 }; 141 142 t.start(); 143 startBarrier.waitFor(); 144 enableAllocationTracking(sameThread ? t : Thread.currentThread(), true); 145 trackBarrier.dec(); 146 147 t.join(); 148 } 149 150 // Our own little barrier, to avoid behind-the-scenes allocations. 151 private static class SimpleBarrier { 152 int count; 153 SimpleBarrier(int i)154 public SimpleBarrier(int i) { 155 count = i; 156 } 157 dec()158 public synchronized void dec() throws Exception { 159 count--; 160 notifyAll(); 161 } 162 waitFor()163 public synchronized void waitFor() throws Exception { 164 while (count != 0) { 165 wait(); 166 } 167 } 168 } 169 setupObjectAllocCallback(boolean enable)170 private static native void setupObjectAllocCallback(boolean enable); 171 enableAllocationTracking(Thread thread, boolean enable)172 private static native void enableAllocationTracking(Thread thread, boolean enable); 173 getAndResetAllocationTrackingString()174 private static native String getAndResetAllocationTrackingString(); 175 } 176