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