1d063d912e5580222b1822b152de315420cef49eeJeff Hao/*
2d063d912e5580222b1822b152de315420cef49eeJeff Hao * Copyright (C) 2014 The Android Open Source Project
3d063d912e5580222b1822b152de315420cef49eeJeff Hao *
4d063d912e5580222b1822b152de315420cef49eeJeff Hao * Licensed under the Apache License, Version 2.0 (the "License");
5d063d912e5580222b1822b152de315420cef49eeJeff Hao * you may not use this file except in compliance with the License.
6d063d912e5580222b1822b152de315420cef49eeJeff Hao * You may obtain a copy of the License at
7d063d912e5580222b1822b152de315420cef49eeJeff Hao *
8d063d912e5580222b1822b152de315420cef49eeJeff Hao *      http://www.apache.org/licenses/LICENSE-2.0
9d063d912e5580222b1822b152de315420cef49eeJeff Hao *
10d063d912e5580222b1822b152de315420cef49eeJeff Hao * Unless required by applicable law or agreed to in writing, software
11d063d912e5580222b1822b152de315420cef49eeJeff Hao * distributed under the License is distributed on an "AS IS" BASIS,
12d063d912e5580222b1822b152de315420cef49eeJeff Hao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d063d912e5580222b1822b152de315420cef49eeJeff Hao * See the License for the specific language governing permissions and
14d063d912e5580222b1822b152de315420cef49eeJeff Hao * limitations under the License.
15d063d912e5580222b1822b152de315420cef49eeJeff Hao */
16d063d912e5580222b1822b152de315420cef49eeJeff Hao
17d063d912e5580222b1822b152de315420cef49eeJeff Haoimport java.io.File;
18d063d912e5580222b1822b152de315420cef49eeJeff Haoimport java.io.IOException;
19d063d912e5580222b1822b152de315420cef49eeJeff Haoimport java.lang.reflect.Method;
20f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartierimport java.util.Arrays;
21f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartierimport java.util.ArrayList;
22a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchiimport java.util.Map;
23d063d912e5580222b1822b152de315420cef49eeJeff Hao
24d063d912e5580222b1822b152de315420cef49eeJeff Haopublic class Main {
25ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz    private static final String TEMP_FILE_NAME_PREFIX = "test";
26ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz    private static final String TEMP_FILE_NAME_SUFFIX = ".trace";
27ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz
28d063d912e5580222b1822b152de315420cef49eeJeff Hao    public static void main(String[] args) throws Exception {
29d063d912e5580222b1822b152de315420cef49eeJeff Hao        String name = System.getProperty("java.vm.name");
30d063d912e5580222b1822b152de315420cef49eeJeff Hao        if (!"Dalvik".equals(name)) {
31d063d912e5580222b1822b152de315420cef49eeJeff Hao            System.out.println("This test is not supported on " + name);
32d063d912e5580222b1822b152de315420cef49eeJeff Hao            return;
33d063d912e5580222b1822b152de315420cef49eeJeff Hao        }
34d063d912e5580222b1822b152de315420cef49eeJeff Hao        testMethodTracing();
35f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        testCountInstances();
36a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        testRuntimeStat();
37f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        testRuntimeStats();
38d063d912e5580222b1822b152de315420cef49eeJeff Hao    }
39d063d912e5580222b1822b152de315420cef49eeJeff Hao
407403503d9ba33463e850b7e87a1b0430372d7003Andreas Gampe    private static File createTempFile() throws Exception {
418cf89c4ac6e09f17093ef0f8c35e86dcd2807d98Jeff Hao        try {
42ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz            return  File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
438cf89c4ac6e09f17093ef0f8c35e86dcd2807d98Jeff Hao        } catch (IOException e) {
447403503d9ba33463e850b7e87a1b0430372d7003Andreas Gampe            System.setProperty("java.io.tmpdir", "/data/local/tmp");
457403503d9ba33463e850b7e87a1b0430372d7003Andreas Gampe            try {
46ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz                return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
477403503d9ba33463e850b7e87a1b0430372d7003Andreas Gampe            } catch (IOException e2) {
487403503d9ba33463e850b7e87a1b0430372d7003Andreas Gampe                System.setProperty("java.io.tmpdir", "/sdcard");
49ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz                return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
507403503d9ba33463e850b7e87a1b0430372d7003Andreas Gampe            }
51d063d912e5580222b1822b152de315420cef49eeJeff Hao        }
527403503d9ba33463e850b7e87a1b0430372d7003Andreas Gampe    }
537403503d9ba33463e850b7e87a1b0430372d7003Andreas Gampe
547403503d9ba33463e850b7e87a1b0430372d7003Andreas Gampe    private static void testMethodTracing() throws Exception {
55ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz        File tempFile = null;
56ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz        try {
57ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz            tempFile = createTempFile();
58ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz            testMethodTracingToFile(tempFile);
59ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz        } finally {
60ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz            if (tempFile != null) {
61ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz                tempFile.delete();
62ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz            }
63ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz        }
64ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz    }
65ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz
66ef3b17732afb70ac70075a0334cb7074761bd507Sebastien Hertz    private static void testMethodTracingToFile(File tempFile) throws Exception {
678cf89c4ac6e09f17093ef0f8c35e86dcd2807d98Jeff Hao        String tempFileName = tempFile.getPath();
68d063d912e5580222b1822b152de315420cef49eeJeff Hao
69cbe15be6f108da7f56c7cb481d2cbed9c568d35aJeff Hao        if (VMDebug.getMethodTracingMode() != 0) {
70cbe15be6f108da7f56c7cb481d2cbed9c568d35aJeff Hao            VMDebug.stopMethodTracing();
71cbe15be6f108da7f56c7cb481d2cbed9c568d35aJeff Hao        }
72cbe15be6f108da7f56c7cb481d2cbed9c568d35aJeff Hao
73d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("Confirm enable/disable");
74d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("status=" + VMDebug.getMethodTracingMode());
75d063d912e5580222b1822b152de315420cef49eeJeff Hao        VMDebug.startMethodTracing(tempFileName, 0, 0, false, 0);
76d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("status=" + VMDebug.getMethodTracingMode());
77d063d912e5580222b1822b152de315420cef49eeJeff Hao        VMDebug.stopMethodTracing();
78d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("status=" + VMDebug.getMethodTracingMode());
79d063d912e5580222b1822b152de315420cef49eeJeff Hao        if (tempFile.length() == 0) {
80d063d912e5580222b1822b152de315420cef49eeJeff Hao            System.out.println("ERROR: tracing output file is empty");
81d063d912e5580222b1822b152de315420cef49eeJeff Hao        }
82d063d912e5580222b1822b152de315420cef49eeJeff Hao
83d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("Confirm sampling");
84d063d912e5580222b1822b152de315420cef49eeJeff Hao        VMDebug.startMethodTracing(tempFileName, 0, 0, true, 1000);
85d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("status=" + VMDebug.getMethodTracingMode());
86d063d912e5580222b1822b152de315420cef49eeJeff Hao        VMDebug.stopMethodTracing();
87d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("status=" + VMDebug.getMethodTracingMode());
88d063d912e5580222b1822b152de315420cef49eeJeff Hao        if (tempFile.length() == 0) {
89d063d912e5580222b1822b152de315420cef49eeJeff Hao            System.out.println("ERROR: sample tracing output file is empty");
90d063d912e5580222b1822b152de315420cef49eeJeff Hao        }
91d063d912e5580222b1822b152de315420cef49eeJeff Hao
92d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("Test starting when already started");
93d063d912e5580222b1822b152de315420cef49eeJeff Hao        VMDebug.startMethodTracing(tempFileName, 0, 0, false, 0);
94d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("status=" + VMDebug.getMethodTracingMode());
95d063d912e5580222b1822b152de315420cef49eeJeff Hao        VMDebug.startMethodTracing(tempFileName, 0, 0, false, 0);
96d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("status=" + VMDebug.getMethodTracingMode());
97d063d912e5580222b1822b152de315420cef49eeJeff Hao
98d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("Test stopping when already stopped");
99d063d912e5580222b1822b152de315420cef49eeJeff Hao        VMDebug.stopMethodTracing();
100d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("status=" + VMDebug.getMethodTracingMode());
101d063d912e5580222b1822b152de315420cef49eeJeff Hao        VMDebug.stopMethodTracing();
102d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("status=" + VMDebug.getMethodTracingMode());
103d063d912e5580222b1822b152de315420cef49eeJeff Hao
104d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("Test tracing with empty filename");
105d063d912e5580222b1822b152de315420cef49eeJeff Hao        try {
106d063d912e5580222b1822b152de315420cef49eeJeff Hao            VMDebug.startMethodTracing("", 0, 0, false, 0);
107d063d912e5580222b1822b152de315420cef49eeJeff Hao            System.out.println("Should have thrown an exception");
108d063d912e5580222b1822b152de315420cef49eeJeff Hao        } catch (Exception e) {
109d063d912e5580222b1822b152de315420cef49eeJeff Hao            System.out.println("Got expected exception");
110d063d912e5580222b1822b152de315420cef49eeJeff Hao        }
111d063d912e5580222b1822b152de315420cef49eeJeff Hao
112d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("Test tracing with bogus (< 1024 && != 0) filesize");
113d063d912e5580222b1822b152de315420cef49eeJeff Hao        try {
114d063d912e5580222b1822b152de315420cef49eeJeff Hao            VMDebug.startMethodTracing(tempFileName, 1000, 0, false, 0);
115d063d912e5580222b1822b152de315420cef49eeJeff Hao            System.out.println("Should have thrown an exception");
116d063d912e5580222b1822b152de315420cef49eeJeff Hao        } catch (Exception e) {
117d063d912e5580222b1822b152de315420cef49eeJeff Hao            System.out.println("Got expected exception");
118d063d912e5580222b1822b152de315420cef49eeJeff Hao        }
119d063d912e5580222b1822b152de315420cef49eeJeff Hao
120d063d912e5580222b1822b152de315420cef49eeJeff Hao        System.out.println("Test sampling with bogus (<= 0) interval");
121d063d912e5580222b1822b152de315420cef49eeJeff Hao        try {
122d063d912e5580222b1822b152de315420cef49eeJeff Hao            VMDebug.startMethodTracing(tempFileName, 0, 0, true, 0);
123d063d912e5580222b1822b152de315420cef49eeJeff Hao            System.out.println("Should have thrown an exception");
124d063d912e5580222b1822b152de315420cef49eeJeff Hao        } catch (Exception e) {
125d063d912e5580222b1822b152de315420cef49eeJeff Hao            System.out.println("Got expected exception");
126d063d912e5580222b1822b152de315420cef49eeJeff Hao        }
127d063d912e5580222b1822b152de315420cef49eeJeff Hao
128d063d912e5580222b1822b152de315420cef49eeJeff Hao        tempFile.delete();
129d063d912e5580222b1822b152de315420cef49eeJeff Hao    }
130d063d912e5580222b1822b152de315420cef49eeJeff Hao
131a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    private static void checkNumber(String s) throws Exception {
132a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        if (s == null) {
133a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            System.out.println("Got null string");
134a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            return;
135a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        }
136a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        long n = Long.valueOf(s);
137a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        if (n < 0) {
138a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            System.out.println("Got negative number " + n);
139a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        }
140a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
141a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi
142a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    private static void checkHistogram(String s) throws Exception {
143a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        if (s == null || s.length() == 0) {
144a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            System.out.println("Got null or empty string");
145a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            return;
146a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        }
147a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String[] buckets = s.split(",");
148a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        long last_key = 0;
149a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        for (int i = 0; i < buckets.length; ++i) {
150a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            String bucket = buckets[i];
151a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            if (bucket.length() == 0) {
152a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                System.out.println("Got empty bucket");
153a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                continue;
154a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            }
155a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            String[] kv = bucket.split(":");
156a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            if (kv.length != 2 || kv[0].length() == 0 || kv[1].length() == 0) {
157a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                System.out.println("Got bad bucket " + bucket);
158a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                continue;
159a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            }
160a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            long key = Long.valueOf(kv[0]);
161a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            long value = Long.valueOf(kv[1]);
162a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            if (key < 0 || value < 0) {
163a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                System.out.println("Got negative key or value " + bucket);
164a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                continue;
165a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            }
166a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            if (key < last_key) {
167a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                System.out.println("Got decreasing key " + bucket);
168a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                continue;
169a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            }
170a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            last_key = key;
171a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        }
172a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
173a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi
174a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    private static void testRuntimeStat() throws Exception {
175a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        // Invoke at least one GC and wait for 20 seconds or so so we get at
176a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        // least one bucket in the histograms.
177a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        for (int i = 0; i < 20; ++i) {
178a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi          Runtime.getRuntime().gc();
179a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi          Thread.sleep(1000L);
180a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        }
181a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String gc_count = VMDebug.getRuntimeStat("art.gc.gc-count");
182a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String gc_time = VMDebug.getRuntimeStat("art.gc.gc-time");
183a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String bytes_allocated = VMDebug.getRuntimeStat("art.gc.bytes-allocated");
184a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String bytes_freed = VMDebug.getRuntimeStat("art.gc.bytes-freed");
185a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String blocking_gc_count = VMDebug.getRuntimeStat("art.gc.blocking-gc-count");
186a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String blocking_gc_time = VMDebug.getRuntimeStat("art.gc.blocking-gc-time");
187a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String gc_count_rate_histogram = VMDebug.getRuntimeStat("art.gc.gc-count-rate-histogram");
188a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String blocking_gc_count_rate_histogram =
189a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            VMDebug.getRuntimeStat("art.gc.blocking-gc-count-rate-histogram");
190a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(gc_count);
191a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(gc_time);
192a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(bytes_allocated);
193a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(bytes_freed);
194a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(blocking_gc_count);
195a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(blocking_gc_time);
196a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkHistogram(gc_count_rate_histogram);
197a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkHistogram(blocking_gc_count_rate_histogram);
198a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
199a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi
200a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    private static void testRuntimeStats() throws Exception {
201a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        // Invoke at least one GC and wait for 20 seconds or so so we get at
202a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        // least one bucket in the histograms.
203a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        for (int i = 0; i < 20; ++i) {
204a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi          Runtime.getRuntime().gc();
205a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi          Thread.sleep(1000L);
206a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        }
207a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        Map<String, String> map = VMDebug.getRuntimeStats();
208a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String gc_count = map.get("art.gc.gc-count");
209a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String gc_time = map.get("art.gc.gc-time");
210a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String bytes_allocated = map.get("art.gc.bytes-allocated");
211a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String bytes_freed = map.get("art.gc.bytes-freed");
212a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String blocking_gc_count = map.get("art.gc.blocking-gc-count");
213a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String blocking_gc_time = map.get("art.gc.blocking-gc-time");
214a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String gc_count_rate_histogram = map.get("art.gc.gc-count-rate-histogram");
215a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        String blocking_gc_count_rate_histogram =
216a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            map.get("art.gc.blocking-gc-count-rate-histogram");
217a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(gc_count);
218a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(gc_time);
219a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(bytes_allocated);
220a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(bytes_freed);
221a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(blocking_gc_count);
222a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkNumber(blocking_gc_time);
223a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkHistogram(gc_count_rate_histogram);
224a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        checkHistogram(blocking_gc_count_rate_histogram);
225a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi    }
226a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi
227f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier    static class ClassA { }
228f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier    static class ClassB { }
229f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier    static class ClassC extends ClassA { }
230f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier
231f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier    private static void testCountInstances() throws Exception {
232f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        ArrayList<Object> l = new ArrayList<Object>();
233f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        l.add(new ClassA());
234f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        l.add(new ClassB());
235f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        l.add(new ClassA());
236f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        l.add(new ClassC());
237f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        Runtime.getRuntime().gc();
238f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        System.out.println("Instances of ClassA " +
239f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier                VMDebug.countInstancesofClass(ClassA.class, false));
240f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        System.out.println("Instances of ClassB " +
241f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier                VMDebug.countInstancesofClass(ClassB.class, false));
242f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        System.out.println("Instances of null " + VMDebug.countInstancesofClass(null, false));
243f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        System.out.println("Instances of ClassA assignable " +
244f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier                VMDebug.countInstancesofClass(ClassA.class, true));
245f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        Class[] classes = new Class[]{ClassA.class, ClassB.class, null};
246f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        long[] counts = VMDebug.countInstancesofClasses(classes, false);
247f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        System.out.println("Array counts " + Arrays.toString(counts));
248f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        counts = VMDebug.countInstancesofClasses(classes, true);
249f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        System.out.println("Array counts assignable " + Arrays.toString(counts));
250f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier    }
251f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier
252d063d912e5580222b1822b152de315420cef49eeJeff Hao    private static class VMDebug {
253d063d912e5580222b1822b152de315420cef49eeJeff Hao        private static final Method startMethodTracingMethod;
254d063d912e5580222b1822b152de315420cef49eeJeff Hao        private static final Method stopMethodTracingMethod;
255d063d912e5580222b1822b152de315420cef49eeJeff Hao        private static final Method getMethodTracingModeMethod;
256a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        private static final Method getRuntimeStatMethod;
257a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        private static final Method getRuntimeStatsMethod;
258f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        private static final Method countInstancesOfClassMethod;
259f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        private static final Method countInstancesOfClassesMethod;
260d063d912e5580222b1822b152de315420cef49eeJeff Hao        static {
261d063d912e5580222b1822b152de315420cef49eeJeff Hao            try {
262d063d912e5580222b1822b152de315420cef49eeJeff Hao                Class c = Class.forName("dalvik.system.VMDebug");
263d063d912e5580222b1822b152de315420cef49eeJeff Hao                startMethodTracingMethod = c.getDeclaredMethod("startMethodTracing", String.class,
264d063d912e5580222b1822b152de315420cef49eeJeff Hao                        Integer.TYPE, Integer.TYPE, Boolean.TYPE, Integer.TYPE);
265d063d912e5580222b1822b152de315420cef49eeJeff Hao                stopMethodTracingMethod = c.getDeclaredMethod("stopMethodTracing");
266d063d912e5580222b1822b152de315420cef49eeJeff Hao                getMethodTracingModeMethod = c.getDeclaredMethod("getMethodTracingMode");
267a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                getRuntimeStatMethod = c.getDeclaredMethod("getRuntimeStat", String.class);
268a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi                getRuntimeStatsMethod = c.getDeclaredMethod("getRuntimeStats");
269f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier                countInstancesOfClassMethod = c.getDeclaredMethod("countInstancesOfClass",
270f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier                        Class.class, Boolean.TYPE);
271f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier                countInstancesOfClassesMethod = c.getDeclaredMethod("countInstancesOfClasses",
272f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier                        Class[].class, Boolean.TYPE);
273d063d912e5580222b1822b152de315420cef49eeJeff Hao            } catch (Exception e) {
274d063d912e5580222b1822b152de315420cef49eeJeff Hao                throw new RuntimeException(e);
275d063d912e5580222b1822b152de315420cef49eeJeff Hao            }
276d063d912e5580222b1822b152de315420cef49eeJeff Hao        }
277d063d912e5580222b1822b152de315420cef49eeJeff Hao
278d063d912e5580222b1822b152de315420cef49eeJeff Hao        public static void startMethodTracing(String filename, int bufferSize, int flags,
279d063d912e5580222b1822b152de315420cef49eeJeff Hao                boolean samplingEnabled, int intervalUs) throws Exception {
280d063d912e5580222b1822b152de315420cef49eeJeff Hao            startMethodTracingMethod.invoke(null, filename, bufferSize, flags, samplingEnabled,
281d063d912e5580222b1822b152de315420cef49eeJeff Hao                    intervalUs);
282d063d912e5580222b1822b152de315420cef49eeJeff Hao        }
283d063d912e5580222b1822b152de315420cef49eeJeff Hao        public static void stopMethodTracing() throws Exception {
284d063d912e5580222b1822b152de315420cef49eeJeff Hao            stopMethodTracingMethod.invoke(null);
285d063d912e5580222b1822b152de315420cef49eeJeff Hao        }
286d063d912e5580222b1822b152de315420cef49eeJeff Hao        public static int getMethodTracingMode() throws Exception {
287d063d912e5580222b1822b152de315420cef49eeJeff Hao            return (int) getMethodTracingModeMethod.invoke(null);
288d063d912e5580222b1822b152de315420cef49eeJeff Hao        }
289a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        public static String getRuntimeStat(String statName) throws Exception {
290a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            return (String) getRuntimeStatMethod.invoke(null, statName);
291a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        }
292a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        public static Map<String, String> getRuntimeStats() throws Exception {
293a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi            return (Map<String, String>) getRuntimeStatsMethod.invoke(null);
294a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi        }
295f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        public static long countInstancesofClass(Class c, boolean assignable) throws Exception {
296f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier            return (long) countInstancesOfClassMethod.invoke(null, new Object[]{c, assignable});
297f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        }
298f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        public static long[] countInstancesofClasses(Class[] classes, boolean assignable)
299f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier                throws Exception {
300f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier            return (long[]) countInstancesOfClassesMethod.invoke(
301f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier                    null, new Object[]{classes, assignable});
302f1820850307f7c2940c758f1232e1c40888a111aMathieu Chartier        }
303d063d912e5580222b1822b152de315420cef49eeJeff Hao    }
304d063d912e5580222b1822b152de315420cef49eeJeff Hao}
305