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 static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
20 
21 import android.annotation.SystemApi;
22 import android.compat.annotation.UnsupportedAppUsage;
23 
24 import java.io.FileDescriptor;
25 import java.io.IOException;
26 import java.util.HashMap;
27 import java.util.Map;
28 
29 import dalvik.annotation.optimization.FastNative;
30 
31 /**
32  * Provides access to some VM-specific debug features. Though this class and
33  * many of its members are public, this class is meant to be wrapped in a more
34  * friendly way for use by application developers. On the Android platform, the
35  * recommended way to access this functionality is through the class
36  * <code>android.os.Debug</code>.
37  *
38  * @hide
39  */
40 @SystemApi(client = MODULE_LIBRARIES)
41 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
42 public final class VMDebug {
43     /**
44      * flag for startMethodTracing(), which adds the results from
45      * startAllocCounting to the trace key file.
46      *
47      * @hide
48      */
49     @SystemApi(client = MODULE_LIBRARIES)
50     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
51     // Must match android.os.Debug.TRACE_COUNT_ALLOCS.
52     public static final int TRACE_COUNT_ALLOCS = 1;
53 
54     /* constants for getAllocCount */
55     private static final int KIND_ALLOCATED_OBJECTS     = 1<<0;
56     private static final int KIND_ALLOCATED_BYTES       = 1<<1;
57     private static final int KIND_FREED_OBJECTS         = 1<<2;
58     private static final int KIND_FREED_BYTES           = 1<<3;
59     private static final int KIND_GC_INVOCATIONS        = 1<<4;
60     private static final int KIND_CLASS_INIT_COUNT      = 1<<5;
61     private static final int KIND_CLASS_INIT_TIME       = 1<<6;
62     private static final int KIND_EXT_ALLOCATED_OBJECTS = 1<<12;
63     private static final int KIND_EXT_ALLOCATED_BYTES   = 1<<13;
64     private static final int KIND_EXT_FREED_OBJECTS     = 1<<14;
65     private static final int KIND_EXT_FREED_BYTES       = 1<<15;
66 
67     /**
68      * Constant for {@link #getAllocCount(int)}
69      * to get the number of all allocated objects.
70      *
71      * @hide
72      */
73     @SystemApi(client = MODULE_LIBRARIES)
74     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
75     public static final int KIND_GLOBAL_ALLOCATED_OBJECTS =
76         KIND_ALLOCATED_OBJECTS;
77 
78     /**
79      * Constant for {@link #getAllocCount(int)}
80      * to get the cumulative size of all objects allocated.
81      *
82      * @hide
83      */
84     @SystemApi(client = MODULE_LIBRARIES)
85     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
86     public static final int KIND_GLOBAL_ALLOCATED_BYTES =
87         KIND_ALLOCATED_BYTES;
88 
89     /**
90      * Constant for {@link #getAllocCount(int)}
91      * to get the number of freed objects.
92      *
93      * @hide
94      */
95     @SystemApi(client = MODULE_LIBRARIES)
96     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
97     public static final int KIND_GLOBAL_FREED_OBJECTS =
98         KIND_FREED_OBJECTS;
99 
100     /**
101      * Constant for {@link #getAllocCount(int)}
102      * to get the cumulative size of all freed objects.
103      *
104      * @hide
105      */
106     @SystemApi(client = MODULE_LIBRARIES)
107     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
108     public static final int KIND_GLOBAL_FREED_BYTES =
109         KIND_FREED_BYTES;
110 
111     /**
112      * Constant for {@link #getAllocCount(int)}
113      * to get the number of times an allocation triggered a blocking GC.
114      *
115      * @hide
116      */
117     @SystemApi(client = MODULE_LIBRARIES)
118     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
119     public static final int KIND_GLOBAL_GC_INVOCATIONS =
120         KIND_GC_INVOCATIONS;
121 
122     /**
123      * Constant for {@link #getAllocCount(int)}
124      * to get the number of initialized classes.
125      *
126      * @hide
127      */
128     @SystemApi(client = MODULE_LIBRARIES)
129     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
130     public static final int KIND_GLOBAL_CLASS_INIT_COUNT =
131         KIND_CLASS_INIT_COUNT;
132 
133     /**
134      * Constant for {@link #getAllocCount(int)}
135      * to get the cumulative time spent in class initialization.
136      *
137      * @hide
138      */
139     @SystemApi(client = MODULE_LIBRARIES)
140     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
141     public static final int KIND_GLOBAL_CLASS_INIT_TIME =
142         KIND_CLASS_INIT_TIME;
143 
144     /**
145      * Constant for {@link #getAllocCount(int)}
146      * to get the number of all allocated objects for current thread.
147      *
148      * @hide
149      */
150     @SystemApi(client = MODULE_LIBRARIES)
151     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
152     public static final int KIND_THREAD_ALLOCATED_OBJECTS =
153         KIND_ALLOCATED_OBJECTS << 16;
154 
155     /**
156      * Constant for {@link #getAllocCount(int)}
157      * to get the cumulative size of all objects allocated for current thread.
158      *
159      * @hide
160      */
161     @SystemApi(client = MODULE_LIBRARIES)
162     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
163     public static final int KIND_THREAD_ALLOCATED_BYTES =
164         KIND_ALLOCATED_BYTES << 16;
165 
166     /**
167      * Constant for {@link #getAllocCount(int)}
168      * to get the number of times an allocation triggered a blocking GC for current thread.
169      *
170      * @hide
171      */
172     @SystemApi(client = MODULE_LIBRARIES)
173     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
174     public static final int KIND_THREAD_GC_INVOCATIONS =
175         KIND_GC_INVOCATIONS << 16;
176 
177     /**
178      * Constant for {@link #getAllocCount(int)} to get all possible stats.
179      *
180      * @hide
181      */
182     @SystemApi(client = MODULE_LIBRARIES)
183     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
184     public static final int KIND_ALL_COUNTS = 0xffffffff;
185 
186     /* all methods are static */
VMDebug()187     private VMDebug() {}
188 
189     /**
190      * Returns the time since the last known debugger activity.
191      *
192      * @return the time in milliseconds, or -1 if the debugger is not connected
193      *
194      * @hide
195      */
196     @SystemApi(client = MODULE_LIBRARIES)
197     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
198     @FastNative
lastDebuggerActivity()199     public static native long lastDebuggerActivity();
200 
201     /**
202      * Determines if debugging is enabled in this VM.  If debugging is not
203      * enabled, a debugger cannot be attached.
204      *
205      * @return true if debugging is enabled
206      *
207      * @hide
208      */
209     @SystemApi(client = MODULE_LIBRARIES)
210     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
211     @FastNative
isDebuggingEnabled()212     public static native boolean isDebuggingEnabled();
213 
214     /**
215      * Determines if a debugger is currently attached.
216      *
217      * @return true if (and only if) a debugger is connected
218      *
219      * @hide
220      */
221     @UnsupportedAppUsage
222     @SystemApi(client = MODULE_LIBRARIES)
223     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
224     @FastNative
isDebuggerConnected()225     public static native boolean isDebuggerConnected();
226 
227     /**
228      * Returns an array of strings that identify VM features.  This is
229      * used by DDMS to determine what sorts of operations the VM can
230      * perform.
231      *
232      * @return array of strings identifying VM features
233      *
234      * @hide
235      */
236     @SystemApi(client = MODULE_LIBRARIES)
237     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
getVmFeatureList()238     public static native String[] getVmFeatureList();
239 
240     /**
241      * Start method tracing, specifying a file name as well as a default
242      * buffer size. See <a
243      * href="{@docRoot}guide/developing/tools/traceview.html"> Running the
244      * Traceview Debugging Program</a> for information about reading
245      * trace files.
246      *
247      * <p>You can use either a fully qualified path and
248      * name, or just a name. If only a name is specified, the file will
249      * be created under the /sdcard/ directory. If a name is not given,
250      * the default is /sdcard/dmtrace.trace.</p>
251      *
252      * @param traceFileName   name to give the trace file
253      * @param bufferSize      the maximum size of both files combined. If passed
254      *                        as {@code 0}, it defaults to 8MB.
255      * @param flags           flags to control method tracing. The only one that
256      *                        is currently defined is {@link #TRACE_COUNT_ALLOCS}.
257      * @param samplingEnabled if true, sample profiling is enabled. Otherwise,
258      *                        method instrumentation is used.
259      * @param intervalUs      the time between samples in microseconds when
260      *                        sampling is enabled.
261      *
262      * @hide
263      */
264     @SystemApi(client = MODULE_LIBRARIES)
265     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
startMethodTracing(String traceFileName, int bufferSize, int flags, boolean samplingEnabled, int intervalUs)266     public static void startMethodTracing(String traceFileName, int bufferSize, int flags, boolean samplingEnabled, int intervalUs) {
267         startMethodTracingFilename(traceFileName, checkBufferSize(bufferSize), flags, samplingEnabled, intervalUs);
268     }
269 
270     /**
271      * Like {@link #startMethodTracing(String, int, int)}, but taking an already-opened
272      * {@code FileDescriptor} in which the trace is written.  The file name is also
273      * supplied simply for logging.  Makes a dup of the file descriptor.
274      * Streams tracing data to the file if streamingOutput is true.
275      *
276      * @param traceFileName   name to give the trace file
277      * @param fd              already opened {@code FileDescriptor} in which trace is written
278      * @param bufferSize      the maximum size of both files combined. If passed
279      *                        as {@code 0}, it defaults to 8MB.
280      * @param flags           flags to control method tracing. The only one that
281      *                        is currently defined is {@link #TRACE_COUNT_ALLOCS}.
282      * @param samplingEnabled if true, sample profiling is enabled. Otherwise,
283      *                        method instrumentation is used.
284      * @param intervalUs      the time between samples in microseconds when
285      *                        sampling is enabled.
286      * @param streamingOutput streams tracing data to the duped {@code fd} file descriptor
287      *                        if {@code streamingOutput} is {@code true}.
288      *
289      * @hide
290      */
291     @SystemApi(client = MODULE_LIBRARIES)
292     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
startMethodTracing(String traceFileName, FileDescriptor fd, int bufferSize, int flags, boolean samplingEnabled, int intervalUs, boolean streamingOutput)293     public static void startMethodTracing(String traceFileName, FileDescriptor fd, int bufferSize,
294                                           int flags, boolean samplingEnabled, int intervalUs,
295                                           boolean streamingOutput) {
296         if (fd == null) {
297             throw new NullPointerException("fd == null");
298         }
299         startMethodTracingFd(traceFileName, fd.getInt$(), checkBufferSize(bufferSize), flags,
300                              samplingEnabled, intervalUs, streamingOutput);
301     }
302 
303     /**
304      * Starts method tracing without a backing file.  When {@link #stopMethodTracing()}
305      * is called, the result is sent directly to DDMS.  (If DDMS is not
306      * attached when tracing ends, the profiling data will be discarded.)
307      *
308      * @param bufferSize      the maximum size of both files combined. If passed
309      *                        as {@code 0}, it defaults to 8MB.
310      * @param flags           flags to control method tracing. The only one that
311      *                        is currently defined is {@link #TRACE_COUNT_ALLOCS}.
312      * @param samplingEnabled if true, sample profiling is enabled. Otherwise,
313      *                        method instrumentation is used.
314      * @param intervalUs      the time between samples in microseconds when
315      *                        sampling is enabled.
316      *
317      * @hide
318      */
319     @SystemApi(client = MODULE_LIBRARIES)
320     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
startMethodTracingDdms(int bufferSize, int flags, boolean samplingEnabled, int intervalUs)321     public static void startMethodTracingDdms(int bufferSize, int flags, boolean samplingEnabled, int intervalUs) {
322         startMethodTracingDdmsImpl(checkBufferSize(bufferSize), flags, samplingEnabled, intervalUs);
323     }
324 
checkBufferSize(int bufferSize)325     private static int checkBufferSize(int bufferSize) {
326         if (bufferSize == 0) {
327             // Default to 8MB per the documentation.
328             bufferSize = 8 * 1024 * 1024;
329         }
330         if (bufferSize < 1024) {
331             throw new IllegalArgumentException("buffer size < 1024: " + bufferSize);
332         }
333         return bufferSize;
334     }
335 
startMethodTracingDdmsImpl(int bufferSize, int flags, boolean samplingEnabled, int intervalUs)336     private static native void startMethodTracingDdmsImpl(int bufferSize, int flags, boolean samplingEnabled, int intervalUs);
startMethodTracingFd(String traceFileName, int fd, int bufferSize, int flags, boolean samplingEnabled, int intervalUs, boolean streamingOutput)337     private static native void startMethodTracingFd(String traceFileName, int fd, int bufferSize,
338             int flags, boolean samplingEnabled, int intervalUs, boolean streamingOutput);
startMethodTracingFilename(String traceFileName, int bufferSize, int flags, boolean samplingEnabled, int intervalUs)339     private static native void startMethodTracingFilename(String traceFileName, int bufferSize, int flags, boolean samplingEnabled, int intervalUs);
340 
341     /**
342      * Determine whether method tracing is currently active and what type is
343      * active.
344      *
345      * @hide
346      */
347     @SystemApi(client = MODULE_LIBRARIES)
348     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
getMethodTracingMode()349     public static native int getMethodTracingMode();
350 
351     /**
352      * Stops method tracing.
353      *
354      * @hide
355      */
356     @SystemApi(client = MODULE_LIBRARIES)
357     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
stopMethodTracing()358     public static native void stopMethodTracing();
359 
360     /**
361      * Get an indication of thread CPU usage. The value returned indicates the
362      * amount of time that the current thread has spent executing code or
363      * waiting for certain types of I/O.
364      * <p>
365      * The time is expressed in nanoseconds, and is only meaningful when
366      * compared to the result from an earlier call. Note that nanosecond
367      * resolution does not imply nanosecond accuracy.
368      *
369      * @return the CPU usage. A value of -1 means the system does not support
370      *         this feature.
371      *
372      * @hide
373      */
374     @SystemApi(client = MODULE_LIBRARIES)
375     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
376     @FastNative
threadCpuTimeNanos()377     public static native long threadCpuTimeNanos();
378 
379     /**
380      * Starts counting the number and aggregate size of memory allocations.
381      *
382      * @hide
383      */
384     @SystemApi(client = MODULE_LIBRARIES)
385     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
startAllocCounting()386     public static native void startAllocCounting();
387 
388     /**
389      * Stops counting the number and aggregate size of memory allocations.
390      *
391      * @hide
392      */
393     @SystemApi(client = MODULE_LIBRARIES)
394     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
stopAllocCounting()395     public static native void stopAllocCounting();
396 
397     /**
398      * Returns information on the number of objects allocated by the runtime between a
399      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
400      *
401      * @param kind either {@code KIND_GLOBAL_*} or {@code KIND_THREAD_*}.
402      *
403      * @hide
404      */
405     @SystemApi(client = MODULE_LIBRARIES)
406     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
getAllocCount(int kind)407     public static native int getAllocCount(int kind);
408 
409     /**
410      * Resets counting the number and aggregate size of memory allocations for the given kinds.
411      *
412      * @param kinds a union of {@code KIND_GLOBAL_*} and {@code KIND_THREAD_*}.
413      *
414      * @hide
415      */
416     @SystemApi(client = MODULE_LIBRARIES)
417     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
resetAllocCount(int kinds)418     public static native void resetAllocCount(int kinds);
419 
420     /**
421      * This method exists for binary compatibility.  It was part of
422      * the allocation limits API which was removed in Android 3.0 (Honeycomb).
423      *
424      * @hide
425      */
426     @Deprecated
setAllocationLimit(int limit)427     public static int setAllocationLimit(int limit) {
428         return -1;
429     }
430 
431     /**
432      * This method exists for binary compatibility.  It was part of
433      * the allocation limits API which was removed in Android 3.0 (Honeycomb).
434      *
435      * @hide
436      */
437     @Deprecated
setGlobalAllocationLimit(int limit)438     public static int setGlobalAllocationLimit(int limit) {
439         return -1;
440     }
441 
442     /**
443      * Count the number of instructions executed between two points.
444      *
445      * @hide
446      */
447     @Deprecated
startInstructionCounting()448     public static void startInstructionCounting() {}
449 
450     /**
451      *
452      * @hide
453      */
454     @Deprecated
stopInstructionCounting()455     public static void stopInstructionCounting() {}
456 
457     /**
458      *
459      * @hide
460      */
461     @Deprecated
getInstructionCount(int[] counts)462     public static void getInstructionCount(int[] counts) {}
463 
464     /**
465      *
466      * @hide
467      */
468     @Deprecated
resetInstructionCount()469     public static void resetInstructionCount() {}
470 
471     /**
472      * Dumps a list of loaded class to the log file.
473      *
474      * @param flags a union of {@link android.os.Debug.SHOW_FULL_DETAIL},
475      *    {@link android.os.Debug.SHOW_CLASSLOADER}, and {@link android.os.Debug.SHOW_INITIALIZED}.
476      *
477      * @hide
478      */
479     @SystemApi(client = MODULE_LIBRARIES)
480     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
481     @FastNative
printLoadedClasses(int flags)482     public static native void printLoadedClasses(int flags);
483 
484     /**
485      * Gets the number of loaded classes.
486      *
487      * @return the number of loaded classes
488      *
489      * @hide
490      */
491     @SystemApi(client = MODULE_LIBRARIES)
492     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
493     @FastNative
getLoadedClassCount()494     public static native int getLoadedClassCount();
495 
496     /**
497      * Dumps "hprof" data to the specified file.  This may cause a GC.
498      *
499      * The VM may create a temporary file in the same directory.
500      *
501      * @param filename Full pathname of output file (e.g. "/sdcard/dump.hprof").
502      * @throws UnsupportedOperationException if the VM was built without
503      *         HPROF support.
504      * @throws IOException if an error occurs while opening or writing files.
505      *
506      * @hide
507      */
508     @SystemApi(client = MODULE_LIBRARIES)
509     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
dumpHprofData(String filename)510     public static void dumpHprofData(String filename) throws IOException {
511         if (filename == null) {
512             throw new NullPointerException("filename == null");
513         }
514         dumpHprofData(filename, null);
515     }
516 
517     /**
518      * Collects "hprof" heap data and sends it to DDMS.  This may cause a GC.
519      *
520      * @throws UnsupportedOperationException if the VM was built without
521      *         HPROF support.
522      *
523      * @hide
524      */
525     @SystemApi(client = MODULE_LIBRARIES)
526     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
dumpHprofDataDdms()527     public static native void dumpHprofDataDdms();
528 
529     /**
530      * Dumps "hprof" heap data to a file, by name or descriptor.
531      *
532      * @param fileName Name of output file.  If fd is non-null, the
533      *        file name is only used in log messages (and may be null).
534      * @param fd Descriptor of open file that will receive the output.
535      *        If this is null, the fileName is used instead.
536      * @throws {@link IOException} if an error occurs while opening or writing files.
537      *
538      * @hide
539      */
540     @SystemApi(client = MODULE_LIBRARIES)
541     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
dumpHprofData(String fileName, FileDescriptor fd)542     public static void dumpHprofData(String fileName, FileDescriptor fd)
543             throws IOException {
544        dumpHprofData(fileName, fd != null ? fd.getInt$() : -1);
545     }
546 
dumpHprofData(String fileName, int fd)547     private static native void dumpHprofData(String fileName, int fd)
548             throws IOException;
549 
550     /**
551      * Dumps the contents of the VM reference tables (e.g. JNI locals and
552      * globals) to the log file.
553      *
554      * @hide
555      */
556     @UnsupportedAppUsage
557     @SystemApi(client = MODULE_LIBRARIES)
558     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
dumpReferenceTables()559     public static native void dumpReferenceTables();
560 
561     /**
562      * Counts the instances of a class.
563      * It is the caller's responsibility to do GC if they don't want unreachable
564      * objects to get counted.
565      *
566      * @param klass the class to be counted.
567      * @param assignable if true, any instance whose class is assignable to
568      *                   {@code klass}, as defined by {@link Class#isAssignableFrom},
569      *                   is counted. If false, only instances whose class is
570      *                   equal to {@code klass} are counted.
571      * @return the number of matching instances.
572      *
573      * @hide
574      */
575     @SystemApi(client = MODULE_LIBRARIES)
576     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
countInstancesOfClass(Class klass, boolean assignable)577     public static native long countInstancesOfClass(Class klass, boolean assignable);
578 
579     /**
580      * Counts the instances of classes.
581      * It is the caller's responsibility to do GC if they don't want unreachable
582      * objects to get counted.
583      *
584      * @param classes the classes to be counted.
585      * @param assignable if true, any instance whose class is assignable to
586      *                   {@code classes[i]}, as defined by {@link Class#isAssignableFrom},
587      *                   is counted. If false, only instances whose class is
588      *                   equal to {@code classes[i]} are counted.
589      * @return an array containing the number of matching instances. The value
590      *         for index {@code i} is the number of instances of
591      *         the class {@code classes[i]}
592      *
593      * @hide
594      */
595     @SystemApi(client = MODULE_LIBRARIES)
596     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
countInstancesOfClasses(Class[] classes, boolean assignable)597     public static native long[] countInstancesOfClasses(Class[] classes, boolean assignable);
598 
599     /**
600      * Gets instances of classes on the Java heap.
601      * It is the caller's responsibility to do GC if they don't want unreachable
602      * objects to be included.
603      *
604      * @param classes the classes to get instances of.
605      * @param assignable if true, any instance whose class is assignable to
606      *                   {@code classes[i]}, as defined by {@link Class#isAssignableFrom},
607      *                   is included. If false, only instances whose class is
608      *                   equal to {@code classes[i]} are included.
609      * @return an array containing the list of matching instances. The value
610      *         for index {@code i} is an array containing the instances
611      *         of the class {@code classes[i]}
612      *
613      * @hide
614      */
getInstancesOfClasses(Class[] classes, boolean assignable)615     public static native Object[][] getInstancesOfClasses(Class[] classes, boolean assignable);
616 
617     /* Map from the names of the runtime stats supported by getRuntimeStat() to their IDs */
618     private static final HashMap<String, Integer> runtimeStatsMap = new HashMap<>();
619 
620     static {
621         runtimeStatsMap.put("art.gc.gc-count", 0);
622         runtimeStatsMap.put("art.gc.gc-time", 1);
623         runtimeStatsMap.put("art.gc.bytes-allocated", 2);
624         runtimeStatsMap.put("art.gc.bytes-freed", 3);
625         runtimeStatsMap.put("art.gc.blocking-gc-count", 4);
626         runtimeStatsMap.put("art.gc.blocking-gc-time", 5);
627         runtimeStatsMap.put("art.gc.gc-count-rate-histogram", 6);
628         runtimeStatsMap.put("art.gc.blocking-gc-count-rate-histogram", 7);
629         runtimeStatsMap.put("art.gc.objects-allocated", 8);
630         runtimeStatsMap.put("art.gc.total-time-waiting-for-gc", 9);
631     }
632 
633     /**
634      * Returns the value of a particular runtime statistic or {@code null} if no
635      * such runtime statistic exists.
636      *
637      * @param statName the name of the runtime statistic to look up.
638      *
639      * @return the value of the runtime statistic.
640      *
641      * @hide
642      */
643     @SystemApi(client = MODULE_LIBRARIES)
644     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
getRuntimeStat(String statName)645     public static String getRuntimeStat(String statName) {
646         if (statName == null) {
647             throw new NullPointerException("statName == null");
648         }
649         Integer statId = runtimeStatsMap.get(statName);
650         if (statId != null) {
651             return getRuntimeStatInternal(statId);
652         }
653         return null;
654     }
655 
656     /**
657      * Returns a map of the names/values of the runtime statistics
658      * that {@link #getRuntimeStat()} supports.
659      *
660      * @return a map of the names/values of the supported runtime statistics.
661      *
662      * @hide
663      */
664     @SystemApi(client = MODULE_LIBRARIES)
665     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
getRuntimeStats()666     public static Map<String, String> getRuntimeStats() {
667         HashMap<String, String> map = new HashMap<>();
668         String[] values = getRuntimeStatsInternal();
669         for (String name : runtimeStatsMap.keySet()) {
670             int id = runtimeStatsMap.get(name);
671             String value = values[id];
672             map.put(name, value);
673         }
674         return map;
675     }
676 
getRuntimeStatInternal(int statId)677     private static native String getRuntimeStatInternal(int statId);
getRuntimeStatsInternal()678     private static native String[] getRuntimeStatsInternal();
679 
680     /**
681      * Attaches an agent to the VM.
682      *
683      * @param agent       The path to the agent .so file plus optional agent arguments.
684      * @param classLoader The classloader to use as a loading context.
685      *
686      * @throws IOException if an error occurs while opening {@code agent} file.
687      *
688      * @hide
689      */
690     @SystemApi(client = MODULE_LIBRARIES)
691     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
attachAgent(String agent, ClassLoader classLoader)692     public static void attachAgent(String agent, ClassLoader classLoader) throws IOException {
693         nativeAttachAgent(agent, classLoader);
694     }
695 
nativeAttachAgent(String agent, ClassLoader classLoader)696     private static native void nativeAttachAgent(String agent, ClassLoader classLoader)
697             throws IOException;
698 
699     /**
700      * Exempts a class from any future non-SDK API access checks.
701      * Methods declared in the class will be allowed to perform
702      * reflection/JNI against the framework completely unrestricted.
703      * Note that this does not affect uses of non-SDK APIs that the class links against.
704      * Note that this does not affect methods declared outside this class, e.g.
705      * inherited from a superclass or an implemented interface.
706      *
707      * @param klass The class whose methods should be exempted.
708      *
709      * @hide
710      */
711     @UnsupportedAppUsage
allowHiddenApiReflectionFrom(Class<?> klass)712     public static native void allowHiddenApiReflectionFrom(Class<?> klass);
713 
714     /**
715      * Sets the number of frames recorded for allocation tracking.
716      *
717      * @param stackDepth The number of frames captured for each stack trace.
718      *
719      * @hide
720      */
721     @SystemApi(client = MODULE_LIBRARIES)
722     @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
setAllocTrackerStackDepth(int stackDepth)723     public static native void setAllocTrackerStackDepth(int stackDepth);
724 }
725