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 
52     enableAllocationTracking(null, true);
53 
54     l.add(new Object());
55     l.add(new Integer(1));
56 
57     enableAllocationTracking(null, false);
58 
59     l.add(new Float(1.0f));
60 
61     enableAllocationTracking(Thread.currentThread(), true);
62 
63     l.add(new Short((short)0));
64 
65     enableAllocationTracking(Thread.currentThread(), false);
66 
67     l.add(new Byte((byte)0));
68 
69     System.out.println(Arrays.toString(getTrackingEventMessages()));
70     System.out.println("Tracking on same thread");
71 
72     testThread(l, true, true);
73 
74     l.add(new Byte((byte)0));
75 
76     System.out.println(Arrays.toString(getTrackingEventMessages()));
77     System.out.println("Tracking on same thread, not disabling tracking");
78 
79     testThread(l, true, false);
80 
81     System.out.println(Arrays.toString(getTrackingEventMessages()));
82     System.out.println("Tracking on different thread");
83 
84     testThread(l, false, true);
85 
86     l.add(new Byte((byte)0));
87 
88     // Disable actual logging callback and re-enable tracking, so we can keep the event enabled and
89     // check that shutdown works correctly.
90     setupObjectAllocCallback(false);
91 
92     System.out.println(Arrays.toString(getTrackingEventMessages()));
93 
94     enableAllocationTracking(null, true);
95   }
96 
testThread(final ArrayList<Object> l, final boolean sameThread, final boolean disableTracking)97   private static void testThread(final ArrayList<Object> l, final boolean sameThread,
98       final boolean disableTracking) throws Exception {
99     final SimpleBarrier startBarrier = new SimpleBarrier(1);
100     final SimpleBarrier trackBarrier = new SimpleBarrier(1);
101     final SimpleBarrier disableBarrier = new SimpleBarrier(1);
102 
103     final Thread thisThread = Thread.currentThread();
104 
105     Thread t = new Thread() {
106       public void run() {
107         try {
108           startBarrier.dec();
109           trackBarrier.waitFor();
110         } catch (Exception e) {
111           e.printStackTrace(System.out);
112           System.exit(1);
113         }
114 
115         l.add(new Double(0.0));
116 
117         if (disableTracking) {
118           enableAllocationTracking(sameThread ? this : thisThread, false);
119         }
120       }
121     };
122 
123     t.start();
124     startBarrier.waitFor();
125     enableAllocationTracking(sameThread ? t : Thread.currentThread(), true);
126     trackBarrier.dec();
127 
128     t.join();
129   }
130 
131   private static class SimpleBarrier {
132     int count;
133 
SimpleBarrier(int i)134     public SimpleBarrier(int i) {
135       count = i;
136     }
137 
dec()138     public synchronized void dec() throws Exception {
139       count--;
140       notifyAll();
141     }
142 
waitFor()143     public synchronized void waitFor() throws Exception  {
144       while (count != 0) {
145         wait();
146       }
147     }
148   }
149 
setupObjectAllocCallback(boolean enable)150   private static native void setupObjectAllocCallback(boolean enable);
enableAllocationTracking(Thread thread, boolean enable)151   private static native void enableAllocationTracking(Thread thread, boolean enable);
getTrackingEventMessages()152   private static native String[] getTrackingEventMessages();
153 }
154