1 /* 2 * Copyright (C) 2014 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 import java.io.File; 18 import java.io.IOException; 19 import java.lang.reflect.Method; 20 import java.util.Map; 21 22 public class Main { main(String[] args)23 public static void main(String[] args) throws Exception { 24 String name = System.getProperty("java.vm.name"); 25 if (!"Dalvik".equals(name)) { 26 System.out.println("This test is not supported on " + name); 27 return; 28 } 29 testMethodTracing(); 30 testRuntimeStat(); 31 } 32 createTempFile()33 private static File createTempFile() throws Exception { 34 try { 35 return File.createTempFile("test", ".trace"); 36 } catch (IOException e) { 37 System.setProperty("java.io.tmpdir", "/data/local/tmp"); 38 try { 39 return File.createTempFile("test", ".trace"); 40 } catch (IOException e2) { 41 System.setProperty("java.io.tmpdir", "/sdcard"); 42 return File.createTempFile("test", ".trace"); 43 } 44 } 45 } 46 testMethodTracing()47 private static void testMethodTracing() throws Exception { 48 File tempFile = createTempFile(); 49 tempFile.deleteOnExit(); 50 String tempFileName = tempFile.getPath(); 51 52 if (VMDebug.getMethodTracingMode() != 0) { 53 VMDebug.stopMethodTracing(); 54 } 55 56 System.out.println("Confirm enable/disable"); 57 System.out.println("status=" + VMDebug.getMethodTracingMode()); 58 VMDebug.startMethodTracing(tempFileName, 0, 0, false, 0); 59 System.out.println("status=" + VMDebug.getMethodTracingMode()); 60 VMDebug.stopMethodTracing(); 61 System.out.println("status=" + VMDebug.getMethodTracingMode()); 62 if (tempFile.length() == 0) { 63 System.out.println("ERROR: tracing output file is empty"); 64 } 65 66 System.out.println("Confirm sampling"); 67 VMDebug.startMethodTracing(tempFileName, 0, 0, true, 1000); 68 System.out.println("status=" + VMDebug.getMethodTracingMode()); 69 VMDebug.stopMethodTracing(); 70 System.out.println("status=" + VMDebug.getMethodTracingMode()); 71 if (tempFile.length() == 0) { 72 System.out.println("ERROR: sample tracing output file is empty"); 73 } 74 75 System.out.println("Test starting when already started"); 76 VMDebug.startMethodTracing(tempFileName, 0, 0, false, 0); 77 System.out.println("status=" + VMDebug.getMethodTracingMode()); 78 VMDebug.startMethodTracing(tempFileName, 0, 0, false, 0); 79 System.out.println("status=" + VMDebug.getMethodTracingMode()); 80 81 System.out.println("Test stopping when already stopped"); 82 VMDebug.stopMethodTracing(); 83 System.out.println("status=" + VMDebug.getMethodTracingMode()); 84 VMDebug.stopMethodTracing(); 85 System.out.println("status=" + VMDebug.getMethodTracingMode()); 86 87 System.out.println("Test tracing with empty filename"); 88 try { 89 VMDebug.startMethodTracing("", 0, 0, false, 0); 90 System.out.println("Should have thrown an exception"); 91 } catch (Exception e) { 92 System.out.println("Got expected exception"); 93 } 94 95 System.out.println("Test tracing with bogus (< 1024 && != 0) filesize"); 96 try { 97 VMDebug.startMethodTracing(tempFileName, 1000, 0, false, 0); 98 System.out.println("Should have thrown an exception"); 99 } catch (Exception e) { 100 System.out.println("Got expected exception"); 101 } 102 103 System.out.println("Test sampling with bogus (<= 0) interval"); 104 try { 105 VMDebug.startMethodTracing(tempFileName, 0, 0, true, 0); 106 System.out.println("Should have thrown an exception"); 107 } catch (Exception e) { 108 System.out.println("Got expected exception"); 109 } 110 111 tempFile.delete(); 112 } 113 checkNumber(String s)114 private static void checkNumber(String s) throws Exception { 115 if (s == null) { 116 System.out.println("Got null string"); 117 return; 118 } 119 long n = Long.valueOf(s); 120 if (n < 0) { 121 System.out.println("Got negative number " + n); 122 } 123 } 124 checkHistogram(String s)125 private static void checkHistogram(String s) throws Exception { 126 if (s == null || s.length() == 0) { 127 System.out.println("Got null or empty string"); 128 return; 129 } 130 String[] buckets = s.split(","); 131 long last_key = 0; 132 for (int i = 0; i < buckets.length; ++i) { 133 String bucket = buckets[i]; 134 if (bucket.length() == 0) { 135 System.out.println("Got empty bucket"); 136 continue; 137 } 138 String[] kv = bucket.split(":"); 139 if (kv.length != 2 || kv[0].length() == 0 || kv[1].length() == 0) { 140 System.out.println("Got bad bucket " + bucket); 141 continue; 142 } 143 long key = Long.valueOf(kv[0]); 144 long value = Long.valueOf(kv[1]); 145 if (key < 0 || value < 0) { 146 System.out.println("Got negative key or value " + bucket); 147 continue; 148 } 149 if (key < last_key) { 150 System.out.println("Got decreasing key " + bucket); 151 continue; 152 } 153 last_key = key; 154 } 155 } 156 testRuntimeStat()157 private static void testRuntimeStat() throws Exception { 158 // Invoke at least one GC and wait for 20 seconds or so so we get at 159 // least one bucket in the histograms. 160 for (int i = 0; i < 20; ++i) { 161 Runtime.getRuntime().gc(); 162 Thread.sleep(1000L); 163 } 164 String gc_count = VMDebug.getRuntimeStat("art.gc.gc-count"); 165 String gc_time = VMDebug.getRuntimeStat("art.gc.gc-time"); 166 String bytes_allocated = VMDebug.getRuntimeStat("art.gc.bytes-allocated"); 167 String bytes_freed = VMDebug.getRuntimeStat("art.gc.bytes-freed"); 168 String blocking_gc_count = VMDebug.getRuntimeStat("art.gc.blocking-gc-count"); 169 String blocking_gc_time = VMDebug.getRuntimeStat("art.gc.blocking-gc-time"); 170 String gc_count_rate_histogram = VMDebug.getRuntimeStat("art.gc.gc-count-rate-histogram"); 171 String blocking_gc_count_rate_histogram = 172 VMDebug.getRuntimeStat("art.gc.blocking-gc-count-rate-histogram"); 173 checkNumber(gc_count); 174 checkNumber(gc_time); 175 checkNumber(bytes_allocated); 176 checkNumber(bytes_freed); 177 checkNumber(blocking_gc_count); 178 checkNumber(blocking_gc_time); 179 checkHistogram(gc_count_rate_histogram); 180 checkHistogram(blocking_gc_count_rate_histogram); 181 } 182 testRuntimeStats()183 private static void testRuntimeStats() throws Exception { 184 // Invoke at least one GC and wait for 20 seconds or so so we get at 185 // least one bucket in the histograms. 186 for (int i = 0; i < 20; ++i) { 187 Runtime.getRuntime().gc(); 188 Thread.sleep(1000L); 189 } 190 Map<String, String> map = VMDebug.getRuntimeStats(); 191 String gc_count = map.get("art.gc.gc-count"); 192 String gc_time = map.get("art.gc.gc-time"); 193 String bytes_allocated = map.get("art.gc.bytes-allocated"); 194 String bytes_freed = map.get("art.gc.bytes-freed"); 195 String blocking_gc_count = map.get("art.gc.blocking-gc-count"); 196 String blocking_gc_time = map.get("art.gc.blocking-gc-time"); 197 String gc_count_rate_histogram = map.get("art.gc.gc-count-rate-histogram"); 198 String blocking_gc_count_rate_histogram = 199 map.get("art.gc.blocking-gc-count-rate-histogram"); 200 checkNumber(gc_count); 201 checkNumber(gc_time); 202 checkNumber(bytes_allocated); 203 checkNumber(bytes_freed); 204 checkNumber(blocking_gc_count); 205 checkNumber(blocking_gc_time); 206 checkHistogram(gc_count_rate_histogram); 207 checkHistogram(blocking_gc_count_rate_histogram); 208 } 209 210 private static class VMDebug { 211 private static final Method startMethodTracingMethod; 212 private static final Method stopMethodTracingMethod; 213 private static final Method getMethodTracingModeMethod; 214 private static final Method getRuntimeStatMethod; 215 private static final Method getRuntimeStatsMethod; 216 static { 217 try { 218 Class c = Class.forName("dalvik.system.VMDebug"); 219 startMethodTracingMethod = c.getDeclaredMethod("startMethodTracing", String.class, 220 Integer.TYPE, Integer.TYPE, Boolean.TYPE, Integer.TYPE); 221 stopMethodTracingMethod = c.getDeclaredMethod("stopMethodTracing"); 222 getMethodTracingModeMethod = c.getDeclaredMethod("getMethodTracingMode"); 223 getRuntimeStatMethod = c.getDeclaredMethod("getRuntimeStat", String.class); 224 getRuntimeStatsMethod = c.getDeclaredMethod("getRuntimeStats"); 225 } catch (Exception e) { 226 throw new RuntimeException(e); 227 } 228 } 229 startMethodTracing(String filename, int bufferSize, int flags, boolean samplingEnabled, int intervalUs)230 public static void startMethodTracing(String filename, int bufferSize, int flags, 231 boolean samplingEnabled, int intervalUs) throws Exception { 232 startMethodTracingMethod.invoke(null, filename, bufferSize, flags, samplingEnabled, 233 intervalUs); 234 } stopMethodTracing()235 public static void stopMethodTracing() throws Exception { 236 stopMethodTracingMethod.invoke(null); 237 } getMethodTracingMode()238 public static int getMethodTracingMode() throws Exception { 239 return (int) getMethodTracingModeMethod.invoke(null); 240 } getRuntimeStat(String statName)241 public static String getRuntimeStat(String statName) throws Exception { 242 return (String) getRuntimeStatMethod.invoke(null, statName); 243 } getRuntimeStats()244 public static Map<String, String> getRuntimeStats() throws Exception { 245 return (Map<String, String>) getRuntimeStatsMethod.invoke(null); 246 } 247 } 248 } 249