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