1 /*
2  * Copyright (C) 2007 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 dalvik.system;
18 
19 import java.io.FileDescriptor;
20 import java.io.IOException;
21 
22 /**
23  * Provides access to some VM-specific debug features. Though this class and
24  * many of its members are public, this class is meant to be wrapped in a more
25  * friendly way for use by application developers. On the Android platform, the
26  * recommended way to access this functionality is through the class
27  * <code>android.os.Debug</code>.
28  *
29  * @hide
30  */
31 public final class VMDebug {
32     /**
33      * flag for startMethodTracing(), which adds the results from
34      * startAllocCounting to the trace key file.
35      */
36     public static final int TRACE_COUNT_ALLOCS = 1;
37 
38     /* constants for getAllocCount */
39     private static final int KIND_ALLOCATED_OBJECTS     = 1<<0;
40     private static final int KIND_ALLOCATED_BYTES       = 1<<1;
41     private static final int KIND_FREED_OBJECTS         = 1<<2;
42     private static final int KIND_FREED_BYTES           = 1<<3;
43     private static final int KIND_GC_INVOCATIONS        = 1<<4;
44     private static final int KIND_CLASS_INIT_COUNT      = 1<<5;
45     private static final int KIND_CLASS_INIT_TIME       = 1<<6;
46     private static final int KIND_EXT_ALLOCATED_OBJECTS = 1<<12;
47     private static final int KIND_EXT_ALLOCATED_BYTES   = 1<<13;
48     private static final int KIND_EXT_FREED_OBJECTS     = 1<<14;
49     private static final int KIND_EXT_FREED_BYTES       = 1<<15;
50 
51     public static final int KIND_GLOBAL_ALLOCATED_OBJECTS =
52         KIND_ALLOCATED_OBJECTS;
53     public static final int KIND_GLOBAL_ALLOCATED_BYTES =
54         KIND_ALLOCATED_BYTES;
55     public static final int KIND_GLOBAL_FREED_OBJECTS =
56         KIND_FREED_OBJECTS;
57     public static final int KIND_GLOBAL_FREED_BYTES =
58         KIND_FREED_BYTES;
59     public static final int KIND_GLOBAL_GC_INVOCATIONS =
60         KIND_GC_INVOCATIONS;
61     public static final int KIND_GLOBAL_CLASS_INIT_COUNT =
62         KIND_CLASS_INIT_COUNT;
63     public static final int KIND_GLOBAL_CLASS_INIT_TIME =
64         KIND_CLASS_INIT_TIME;
65     public static final int KIND_GLOBAL_EXT_ALLOCATED_OBJECTS =
66         KIND_EXT_ALLOCATED_OBJECTS;
67     public static final int KIND_GLOBAL_EXT_ALLOCATED_BYTES =
68         KIND_EXT_ALLOCATED_BYTES;
69     public static final int KIND_GLOBAL_EXT_FREED_OBJECTS =
70         KIND_EXT_FREED_OBJECTS;
71     public static final int KIND_GLOBAL_EXT_FREED_BYTES =
72         KIND_EXT_FREED_BYTES;
73 
74     public static final int KIND_THREAD_ALLOCATED_OBJECTS =
75         KIND_ALLOCATED_OBJECTS << 16;
76     public static final int KIND_THREAD_ALLOCATED_BYTES =
77         KIND_ALLOCATED_BYTES << 16;
78     public static final int KIND_THREAD_FREED_OBJECTS =
79         KIND_FREED_OBJECTS << 16;
80     public static final int KIND_THREAD_FREED_BYTES =
81         KIND_FREED_BYTES << 16;
82     public static final int KIND_THREAD_GC_INVOCATIONS =
83         KIND_GC_INVOCATIONS << 16;
84     public static final int KIND_THREAD_CLASS_INIT_COUNT =
85         KIND_CLASS_INIT_COUNT << 16;
86     public static final int KIND_THREAD_CLASS_INIT_TIME =
87         KIND_CLASS_INIT_TIME << 16;
88     public static final int KIND_THREAD_EXT_ALLOCATED_OBJECTS =
89         KIND_EXT_ALLOCATED_OBJECTS << 16;
90     public static final int KIND_THREAD_EXT_ALLOCATED_BYTES =
91         KIND_EXT_ALLOCATED_BYTES << 16;
92     public static final int KIND_THREAD_EXT_FREED_OBJECTS =
93         KIND_EXT_FREED_OBJECTS << 16;
94     public static final int KIND_THREAD_EXT_FREED_BYTES =
95         KIND_EXT_FREED_BYTES << 16;
96 
97     public static final int KIND_ALL_COUNTS = 0xffffffff;
98 
99     /* all methods are static */
VMDebug()100     private VMDebug() {}
101 
102     /**
103      * Returns the time since the last known debugger activity.
104      *
105      * @return the time in milliseconds, or -1 if the debugger is not connected
106      */
lastDebuggerActivity()107     public static native long lastDebuggerActivity();
108 
109     /**
110      * Determines if debugging is enabled in this VM.  If debugging is not
111      * enabled, a debugger cannot be attached.
112      *
113      * @return true if debugging is enabled
114      */
isDebuggingEnabled()115     public static native boolean isDebuggingEnabled();
116 
117     /**
118      * Determines if a debugger is currently attached.
119      *
120      * @return true if (and only if) a debugger is connected
121      */
isDebuggerConnected()122     public static native boolean isDebuggerConnected();
123 
124     /**
125      * Returns an array of strings that identify VM features.  This is
126      * used by DDMS to determine what sorts of operations the VM can
127      * perform.
128      */
getVmFeatureList()129     public static native String[] getVmFeatureList();
130 
131     /**
132      * Start method tracing with default name, size, and with <code>0</code>
133      * flags.
134      *
135      * @deprecated Not used, not needed.
136      */
137     @Deprecated
startMethodTracing()138     public static void startMethodTracing() {
139         throw new UnsupportedOperationException();
140     }
141 
142     /**
143      * Start method tracing, specifying a file name as well as a default
144      * buffer size. See <a
145      * href="{@docRoot}guide/developing/tools/traceview.html"> Running the
146      * Traceview Debugging Program</a> for information about reading
147      * trace files.
148      *
149      * <p>You can use either a fully qualified path and
150      * name, or just a name. If only a name is specified, the file will
151      * be created under the /sdcard/ directory. If a name is not given,
152      * the default is /sdcard/dmtrace.trace.</p>
153      *
154      * @param traceFileName name to give the trace file
155      * @param bufferSize the maximum size of both files combined. If passed
156      * as <code>0</code>, it defaults to 8MB.
157      * @param flags flags to control method tracing. The only one that
158      * is currently defined is {@link #TRACE_COUNT_ALLOCS}.
159      * @param samplingEnabled if true, sample profiling is enabled. Otherwise,
160      * method instrumentation is used.
161      * @param intervalUs the time between samples in microseconds when
162      * sampling is enabled.
163      */
startMethodTracing(String traceFileName, int bufferSize, int flags, boolean samplingEnabled, int intervalUs)164     public static void startMethodTracing(String traceFileName, int bufferSize, int flags, boolean samplingEnabled, int intervalUs) {
165         startMethodTracingFilename(traceFileName, checkBufferSize(bufferSize), flags, samplingEnabled, intervalUs);
166     }
167 
168     /**
169      * Like startMethodTracing(String, int, int), but taking an already-opened
170      * FileDescriptor in which the trace is written.  The file name is also
171      * supplied simply for logging.  Makes a dup of the file descriptor.
172      */
startMethodTracing(String traceFileName, FileDescriptor fd, int bufferSize, int flags, boolean samplingEnabled, int intervalUs)173     public static void startMethodTracing(String traceFileName, FileDescriptor fd, int bufferSize, int flags, boolean samplingEnabled, int intervalUs) {
174         if (fd == null) {
175             throw new NullPointerException("fd == null");
176         }
177         startMethodTracingFd(traceFileName, fd, checkBufferSize(bufferSize), flags, samplingEnabled, intervalUs);
178     }
179 
180     /**
181      * Starts method tracing without a backing file.  When stopMethodTracing
182      * is called, the result is sent directly to DDMS.  (If DDMS is not
183      * attached when tracing ends, the profiling data will be discarded.)
184      */
startMethodTracingDdms(int bufferSize, int flags, boolean samplingEnabled, int intervalUs)185     public static void startMethodTracingDdms(int bufferSize, int flags, boolean samplingEnabled, int intervalUs) {
186         startMethodTracingDdmsImpl(checkBufferSize(bufferSize), flags, samplingEnabled, intervalUs);
187     }
188 
checkBufferSize(int bufferSize)189     private static int checkBufferSize(int bufferSize) {
190         if (bufferSize == 0) {
191             // Default to 8MB per the documentation.
192             bufferSize = 8 * 1024 * 1024;
193         }
194         if (bufferSize < 1024) {
195             throw new IllegalArgumentException("buffer size < 1024: " + bufferSize);
196         }
197         return bufferSize;
198     }
199 
startMethodTracingDdmsImpl(int bufferSize, int flags, boolean samplingEnabled, int intervalUs)200     private static native void startMethodTracingDdmsImpl(int bufferSize, int flags, boolean samplingEnabled, int intervalUs);
startMethodTracingFd(String traceFileName, FileDescriptor fd, int bufferSize, int flags, boolean samplingEnabled, int intervalUs)201     private static native void startMethodTracingFd(String traceFileName, FileDescriptor fd, int bufferSize, int flags, boolean samplingEnabled, int intervalUs);
startMethodTracingFilename(String traceFileName, int bufferSize, int flags, boolean samplingEnabled, int intervalUs)202     private static native void startMethodTracingFilename(String traceFileName, int bufferSize, int flags, boolean samplingEnabled, int intervalUs);
203 
204     /**
205      * Determine whether method tracing is currently active and what type is
206      * active.
207      */
getMethodTracingMode()208     public static native int getMethodTracingMode();
209 
210     /**
211      * Stops method tracing.
212      */
stopMethodTracing()213     public static native void stopMethodTracing();
214 
215     /**
216      * Starts sending Dalvik method trace info to the emulator.
217      */
startEmulatorTracing()218     public static native void startEmulatorTracing();
219 
220     /**
221      * Stops sending Dalvik method trace info to the emulator.
222      */
stopEmulatorTracing()223     public static native void stopEmulatorTracing();
224 
225     /**
226      * Get an indication of thread CPU usage. The value returned indicates the
227      * amount of time that the current thread has spent executing code or
228      * waiting for certain types of I/O.
229      * <p>
230      * The time is expressed in nanoseconds, and is only meaningful when
231      * compared to the result from an earlier call. Note that nanosecond
232      * resolution does not imply nanosecond accuracy.
233      *
234      * @return the CPU usage. A value of -1 means the system does not support
235      *         this feature.
236      */
threadCpuTimeNanos()237     public static native long threadCpuTimeNanos();
238 
239     /**
240      * Count the number and aggregate size of memory allocations between
241      * two points.
242      */
startAllocCounting()243     public static native void startAllocCounting();
stopAllocCounting()244     public static native void stopAllocCounting();
getAllocCount(int kind)245     public static native int getAllocCount(int kind);
resetAllocCount(int kinds)246     public static native void resetAllocCount(int kinds);
247 
248     /**
249      * This method exists for binary compatibility.  It was part of
250      * the allocation limits API which was removed in Android 3.0 (Honeycomb).
251      */
252     @Deprecated
setAllocationLimit(int limit)253     public static int setAllocationLimit(int limit) {
254         return -1;
255     }
256 
257     /**
258      * This method exists for binary compatibility.  It was part of
259      * the allocation limits API which was removed in Android 3.0 (Honeycomb).
260      */
261     @Deprecated
setGlobalAllocationLimit(int limit)262     public static int setGlobalAllocationLimit(int limit) {
263         return -1;
264     }
265 
266     /**
267      * Count the number of instructions executed between two points.
268      */
startInstructionCounting()269     public static native void startInstructionCounting();
stopInstructionCounting()270     public static native void stopInstructionCounting();
getInstructionCount(int[] counts)271     public static native void getInstructionCount(int[] counts);
resetInstructionCount()272     public static native void resetInstructionCount();
273 
274     /**
275      * Dumps a list of loaded class to the log file.
276      */
printLoadedClasses(int flags)277     public static native void printLoadedClasses(int flags);
278 
279     /**
280      * Gets the number of loaded classes.
281      *
282      * @return the number of loaded classes
283      */
getLoadedClassCount()284     public static native int getLoadedClassCount();
285 
286     /**
287      * Dumps "hprof" data to the specified file.  This may cause a GC.
288      *
289      * The VM may create a temporary file in the same directory.
290      *
291      * @param filename Full pathname of output file (e.g. "/sdcard/dump.hprof").
292      * @throws UnsupportedOperationException if the VM was built without
293      *         HPROF support.
294      * @throws IOException if an error occurs while opening or writing files.
295      */
dumpHprofData(String filename)296     public static void dumpHprofData(String filename) throws IOException {
297         if (filename == null) {
298             throw new NullPointerException("filename == null");
299         }
300         dumpHprofData(filename, null);
301     }
302 
303     /**
304      * Collects "hprof" heap data and sends it to DDMS.  This may cause a GC.
305      *
306      * @throws UnsupportedOperationException if the VM was built without
307      *         HPROF support.
308      */
dumpHprofDataDdms()309     public static native void dumpHprofDataDdms();
310 
311     /**
312      * Dumps "hprof" heap data to a file, by name or descriptor.
313      *
314      * @param fileName Name of output file.  If fd is non-null, the
315      *        file name is only used in log messages (and may be null).
316      * @param fd Descriptor of open file that will receive the output.
317      *        If this is null, the fileName is used instead.
318      */
dumpHprofData(String fileName, FileDescriptor fd)319     public static native void dumpHprofData(String fileName, FileDescriptor fd)
320             throws IOException;
321 
322     /**
323      * Primes the register map cache.
324      */
cacheRegisterMap(String classAndMethodDesc)325     public static native boolean cacheRegisterMap(String classAndMethodDesc);
326 
327     /**
328      * Dumps the contents of the VM reference tables (e.g. JNI locals and
329      * globals) to the log file.
330      */
dumpReferenceTables()331     public static native void dumpReferenceTables();
332 
333     /**
334      * Crashes the VM.  Seriously.  Dumps the interpreter stack trace for
335      * the current thread and then aborts the VM so you can see the native
336      * stack trace.  Useful for figuring out how you got somewhere when
337      * lots of native code is involved.
338      */
crash()339     public static native void crash();
340 
341     /**
342      * Together with gdb, provide a handy way to stop the VM at user-tagged
343      * locations.
344      */
infopoint(int id)345     public static native void infopoint(int id);
346 
347     /*
348      * Fake method, inserted into dmtrace output when the garbage collector
349      * runs.  Not actually called.
350      */
startGC()351     private static void startGC() {}
352 
353     /*
354      * Fake method, inserted into dmtrace output during class preparation
355      * (loading and linking, but not verification or initialization).  Not
356      * actually called.
357      */
startClassPrep()358     private static void startClassPrep() {}
359 
360     /**
361      * Counts the instances of a class.
362      *
363      * @param klass the class to be counted.
364      * @param assignable if false, direct instances of klass are
365      *                   counted.  If true, instances that are
366      *                   assignable to klass, as defined by
367      *                   {@link Class#isAssignableFrom} are counted.
368      * @return the number of matching instances.
369      */
countInstancesOfClass(Class klass, boolean assignable)370     public static native long countInstancesOfClass(Class klass, boolean assignable);
371 
372     /**
373      * Export the heap per-space stats for dumpsys meminfo.
374      *
375      * The content of the array is:
376      *
377      * <pre>
378      *   data[0] : the application heap space size
379      *   data[1] : the application heap space allocated bytes
380      *   data[2] : the application heap space free bytes
381      *   data[3] : the zygote heap space size
382      *   data[4] : the zygote heap space allocated size
383      *   data[5] : the zygote heap space free size
384      *   data[6] : the large object space size
385      *   data[7] : the large object space allocated bytes
386      *   data[8] : the large object space free bytes
387      * </pre>
388      *
389      * @param data the array into which the stats are written.
390      */
getHeapSpaceStats(long[] data)391     public static native void getHeapSpaceStats(long[] data);
392 }
393