dalvik_system_VMDebug.cpp revision 4308417beec548c2b2c06ecec4f7f4a965b09fb2
1/*
2 * Copyright (C) 2008 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/*
18 * dalvik.system.VMDebug
19 */
20#include "Dalvik.h"
21#include "native/InternalNativePriv.h"
22#include "hprof/Hprof.h"
23
24#include <string.h>
25#include <unistd.h>
26
27
28/*
29 * Extracts the fd from a FileDescriptor object.
30 *
31 * If an error is encountered, or the extracted descriptor is numerically
32 * invalid, this returns -1 with an exception raised.
33 */
34static int getFileDescriptor(Object* obj)
35{
36    assert(obj != NULL);
37    assert(strcmp(obj->clazz->descriptor, "Ljava/io/FileDescriptor;") == 0);
38
39    int fd = dvmGetFieldInt(obj, gDvm.offJavaIoFileDescriptor_descriptor);
40    if (fd < 0) {
41        dvmThrowRuntimeException("Invalid file descriptor");
42        return -1;
43    }
44
45    return fd;
46}
47
48/*
49 * static String[] getVmFeatureList()
50 *
51 * Return a set of strings describing available VM features (this is chiefly
52 * of interest to DDMS).
53 */
54static void Dalvik_dalvik_system_VMDebug_getVmFeatureList(const u4* args, JValue* pResult) {
55    std::vector<std::string> features;
56    features.push_back("method-trace-profiling");
57    features.push_back("method-trace-profiling-streaming");
58    features.push_back("hprof-heap-dump");
59    features.push_back("hprof-heap-dump-streaming");
60
61    ArrayObject* result = dvmCreateStringArray(features);
62    dvmReleaseTrackedAlloc((Object*) result, dvmThreadSelf());
63    RETURN_PTR(result);
64}
65
66/* These must match the values in dalvik.system.VMDebug.
67 */
68enum {
69    KIND_ALLOCATED_OBJECTS      = 1<<0,
70    KIND_ALLOCATED_BYTES        = 1<<1,
71    KIND_FREED_OBJECTS          = 1<<2,
72    KIND_FREED_BYTES            = 1<<3,
73    KIND_GC_INVOCATIONS         = 1<<4,
74    KIND_CLASS_INIT_COUNT       = 1<<5,
75    KIND_CLASS_INIT_TIME        = 1<<6,
76
77    /* These values exist for backward compatibility. */
78    KIND_EXT_ALLOCATED_OBJECTS = 1<<12,
79    KIND_EXT_ALLOCATED_BYTES   = 1<<13,
80    KIND_EXT_FREED_OBJECTS     = 1<<14,
81    KIND_EXT_FREED_BYTES       = 1<<15,
82
83    KIND_GLOBAL_ALLOCATED_OBJECTS   = KIND_ALLOCATED_OBJECTS,
84    KIND_GLOBAL_ALLOCATED_BYTES     = KIND_ALLOCATED_BYTES,
85    KIND_GLOBAL_FREED_OBJECTS       = KIND_FREED_OBJECTS,
86    KIND_GLOBAL_FREED_BYTES         = KIND_FREED_BYTES,
87    KIND_GLOBAL_GC_INVOCATIONS      = KIND_GC_INVOCATIONS,
88    KIND_GLOBAL_CLASS_INIT_COUNT    = KIND_CLASS_INIT_COUNT,
89    KIND_GLOBAL_CLASS_INIT_TIME     = KIND_CLASS_INIT_TIME,
90
91    KIND_THREAD_ALLOCATED_OBJECTS   = KIND_ALLOCATED_OBJECTS << 16,
92    KIND_THREAD_ALLOCATED_BYTES     = KIND_ALLOCATED_BYTES << 16,
93    KIND_THREAD_FREED_OBJECTS       = KIND_FREED_OBJECTS << 16,
94    KIND_THREAD_FREED_BYTES         = KIND_FREED_BYTES << 16,
95
96    KIND_THREAD_GC_INVOCATIONS      = KIND_GC_INVOCATIONS << 16,
97
98    // TODO: failedAllocCount, failedAllocSize
99};
100
101#define KIND_ALL_COUNTS 0xffffffff
102
103/*
104 * Zero out the specified fields.
105 */
106static void clearAllocProfStateFields(AllocProfState *allocProf,
107    unsigned int kinds)
108{
109    if (kinds & KIND_ALLOCATED_OBJECTS) {
110        allocProf->allocCount = 0;
111    }
112    if (kinds & KIND_ALLOCATED_BYTES) {
113        allocProf->allocSize = 0;
114    }
115    if (kinds & KIND_FREED_OBJECTS) {
116        allocProf->freeCount = 0;
117    }
118    if (kinds & KIND_FREED_BYTES) {
119        allocProf->freeSize = 0;
120    }
121    if (kinds & KIND_GC_INVOCATIONS) {
122        allocProf->gcCount = 0;
123    }
124    if (kinds & KIND_CLASS_INIT_COUNT) {
125        allocProf->classInitCount = 0;
126    }
127    if (kinds & KIND_CLASS_INIT_TIME) {
128        allocProf->classInitTime = 0;
129    }
130}
131
132/*
133 * static void startAllocCounting()
134 *
135 * Reset the counters and enable counting.
136 *
137 * TODO: this currently only resets the per-thread counters for the current
138 * thread.  If we actually start using the per-thread counters we'll
139 * probably want to fix this.
140 */
141static void Dalvik_dalvik_system_VMDebug_startAllocCounting(const u4* args,
142    JValue* pResult)
143{
144    UNUSED_PARAMETER(args);
145
146    clearAllocProfStateFields(&gDvm.allocProf, KIND_ALL_COUNTS);
147    clearAllocProfStateFields(&dvmThreadSelf()->allocProf, KIND_ALL_COUNTS);
148    dvmStartAllocCounting();
149    RETURN_VOID();
150}
151
152/*
153 * public static void stopAllocCounting()
154 */
155static void Dalvik_dalvik_system_VMDebug_stopAllocCounting(const u4* args,
156    JValue* pResult)
157{
158    UNUSED_PARAMETER(args);
159
160    dvmStopAllocCounting();
161    RETURN_VOID();
162}
163
164/*
165 * private static int getAllocCount(int kind)
166 */
167static void Dalvik_dalvik_system_VMDebug_getAllocCount(const u4* args,
168    JValue* pResult)
169{
170    AllocProfState *allocProf;
171    unsigned int kind = args[0];
172    if (kind < (1<<16)) {
173        allocProf = &gDvm.allocProf;
174    } else {
175        allocProf = &dvmThreadSelf()->allocProf;
176        kind >>= 16;
177    }
178    switch (kind) {
179    case KIND_ALLOCATED_OBJECTS:
180        pResult->i = allocProf->allocCount;
181        break;
182    case KIND_ALLOCATED_BYTES:
183        pResult->i = allocProf->allocSize;
184        break;
185    case KIND_FREED_OBJECTS:
186        pResult->i = allocProf->freeCount;
187        break;
188    case KIND_FREED_BYTES:
189        pResult->i = allocProf->freeSize;
190        break;
191    case KIND_GC_INVOCATIONS:
192        pResult->i = allocProf->gcCount;
193        break;
194    case KIND_CLASS_INIT_COUNT:
195        pResult->i = allocProf->classInitCount;
196        break;
197    case KIND_CLASS_INIT_TIME:
198        /* convert nsec to usec, reduce to 32 bits */
199        pResult->i = (int) (allocProf->classInitTime / 1000);
200        break;
201    case KIND_EXT_ALLOCATED_OBJECTS:
202    case KIND_EXT_ALLOCATED_BYTES:
203    case KIND_EXT_FREED_OBJECTS:
204    case KIND_EXT_FREED_BYTES:
205        pResult->i = 0;  /* backward compatibility */
206        break;
207    default:
208        assert(false);
209        pResult->i = -1;
210    }
211}
212
213/*
214 * public static void resetAllocCount(int kinds)
215 */
216static void Dalvik_dalvik_system_VMDebug_resetAllocCount(const u4* args,
217    JValue* pResult)
218{
219    unsigned int kinds = args[0];
220    clearAllocProfStateFields(&gDvm.allocProf, kinds & 0xffff);
221    clearAllocProfStateFields(&dvmThreadSelf()->allocProf, kinds >> 16);
222    RETURN_VOID();
223}
224
225/*
226 * static void startMethodTracingNative(String traceFileName,
227 *     FileDescriptor fd, int bufferSize, int flags)
228 *
229 * Start method trace profiling.
230 *
231 * If both "traceFileName" and "fd" are null, the result will be sent
232 * directly to DDMS.  (The non-DDMS versions of the calls are expected
233 * to enforce non-NULL filenames.)
234 */
235static void Dalvik_dalvik_system_VMDebug_startMethodTracingNative(const u4* args,
236    JValue* pResult)
237{
238    StringObject* traceFileStr = (StringObject*) args[0];
239    Object* traceFd = (Object*) args[1];
240    int bufferSize = args[2];
241    int flags = args[3];
242
243    if (bufferSize == 0) {
244        // Default to 8MB per the documentation.
245        bufferSize = 8 * 1024 * 1024;
246    }
247
248    if (bufferSize < 1024) {
249        dvmThrowIllegalArgumentException(NULL);
250        RETURN_VOID();
251    }
252
253    char* traceFileName = NULL;
254    if (traceFileStr != NULL)
255        traceFileName = dvmCreateCstrFromString(traceFileStr);
256
257    int fd = -1;
258    if (traceFd != NULL) {
259        int origFd = getFileDescriptor(traceFd);
260        if (origFd < 0)
261            RETURN_VOID();
262
263        fd = dup(origFd);
264        if (fd < 0) {
265            dvmThrowExceptionFmt(gDvm.exRuntimeException,
266                "dup(%d) failed: %s", origFd, strerror(errno));
267            RETURN_VOID();
268        }
269    }
270
271    dvmMethodTraceStart(traceFileName != NULL ? traceFileName : "[DDMS]",
272        fd, bufferSize, flags, (traceFileName == NULL && fd == -1));
273    free(traceFileName);
274    RETURN_VOID();
275}
276
277/*
278 * static boolean isMethodTracingActive()
279 *
280 * Determine whether method tracing is currently active.
281 */
282static void Dalvik_dalvik_system_VMDebug_isMethodTracingActive(const u4* args,
283    JValue* pResult)
284{
285    UNUSED_PARAMETER(args);
286
287    RETURN_BOOLEAN(dvmIsMethodTraceActive());
288}
289
290/*
291 * static void stopMethodTracing()
292 *
293 * Stop method tracing.
294 */
295static void Dalvik_dalvik_system_VMDebug_stopMethodTracing(const u4* args,
296    JValue* pResult)
297{
298    UNUSED_PARAMETER(args);
299
300    dvmMethodTraceStop();
301    RETURN_VOID();
302}
303
304/*
305 * static void startEmulatorTracing()
306 *
307 * Start sending method trace info to the emulator.
308 */
309static void Dalvik_dalvik_system_VMDebug_startEmulatorTracing(const u4* args,
310    JValue* pResult)
311{
312    UNUSED_PARAMETER(args);
313
314    dvmEmulatorTraceStart();
315    RETURN_VOID();
316}
317
318/*
319 * static void stopEmulatorTracing()
320 *
321 * Start sending method trace info to the emulator.
322 */
323static void Dalvik_dalvik_system_VMDebug_stopEmulatorTracing(const u4* args,
324    JValue* pResult)
325{
326    UNUSED_PARAMETER(args);
327
328    dvmEmulatorTraceStop();
329    RETURN_VOID();
330}
331
332/*
333 * static boolean isDebuggerConnected()
334 *
335 * Returns "true" if a debugger is attached.
336 */
337static void Dalvik_dalvik_system_VMDebug_isDebuggerConnected(const u4* args,
338    JValue* pResult)
339{
340    UNUSED_PARAMETER(args);
341
342    RETURN_BOOLEAN(dvmDbgIsDebuggerConnected());
343}
344
345/*
346 * static boolean isDebuggingEnabled()
347 *
348 * Returns "true" if debugging is enabled.
349 */
350static void Dalvik_dalvik_system_VMDebug_isDebuggingEnabled(const u4* args,
351    JValue* pResult)
352{
353    UNUSED_PARAMETER(args);
354
355    RETURN_BOOLEAN(gDvm.jdwpConfigured);
356}
357
358/*
359 * static long lastDebuggerActivity()
360 *
361 * Returns the time, in msec, since we last had an interaction with the
362 * debugger (send or receive).
363 */
364static void Dalvik_dalvik_system_VMDebug_lastDebuggerActivity(const u4* args,
365    JValue* pResult)
366{
367    UNUSED_PARAMETER(args);
368
369    RETURN_LONG(dvmDbgLastDebuggerActivity());
370}
371
372/*
373 * static void startInstructionCounting()
374 */
375static void Dalvik_dalvik_system_VMDebug_startInstructionCounting(const u4* args,
376    JValue* pResult)
377{
378    dvmStartInstructionCounting();
379    RETURN_VOID();
380}
381
382/*
383 * static void stopInstructionCounting()
384 */
385static void Dalvik_dalvik_system_VMDebug_stopInstructionCounting(const u4* args,
386    JValue* pResult)
387{
388    dvmStopInstructionCounting();
389    RETURN_VOID();
390}
391
392/*
393 * static boolean getInstructionCount(int[] counts)
394 *
395 * Grab a copy of the global instruction count array.
396 *
397 * Since the instruction counts aren't synchronized, we use sched_yield
398 * to improve our chances of finishing without contention.  (Only makes
399 * sense on a uniprocessor.)
400 */
401static void Dalvik_dalvik_system_VMDebug_getInstructionCount(const u4* args,
402    JValue* pResult)
403{
404    ArrayObject* countArray = (ArrayObject*) args[0];
405
406    if (countArray != NULL) {
407        int* storage = (int*)(void*)countArray->contents;
408        u4 length = countArray->length;
409
410        /*
411         * Ensure that we copy at most kNumPackedOpcodes
412         * elements, but no more than the length of the given array.
413         */
414        if (length > kNumPackedOpcodes) {
415            length = kNumPackedOpcodes;
416        }
417
418        sched_yield();
419        memcpy(storage, gDvm.executedInstrCounts, length * sizeof(int));
420    }
421
422    RETURN_VOID();
423}
424
425/*
426 * static boolean resetInstructionCount()
427 *
428 * Reset the instruction count array.
429 */
430static void Dalvik_dalvik_system_VMDebug_resetInstructionCount(const u4* args,
431    JValue* pResult)
432{
433    sched_yield();
434    memset(gDvm.executedInstrCounts, 0, kNumPackedOpcodes * sizeof(int));
435    RETURN_VOID();
436}
437
438/*
439 * static void printLoadedClasses(int flags)
440 *
441 * Dump the list of loaded classes.
442 */
443static void Dalvik_dalvik_system_VMDebug_printLoadedClasses(const u4* args,
444    JValue* pResult)
445{
446    int flags = args[0];
447
448    dvmDumpAllClasses(flags);
449
450    RETURN_VOID();
451}
452
453/*
454 * static int getLoadedClassCount()
455 *
456 * Return the number of loaded classes
457 */
458static void Dalvik_dalvik_system_VMDebug_getLoadedClassCount(const u4* args,
459    JValue* pResult)
460{
461    int count;
462
463    UNUSED_PARAMETER(args);
464
465    count = dvmGetNumLoadedClasses();
466
467    RETURN_INT(count);
468}
469
470/*
471 * Returns the thread-specific CPU-time clock value for the current thread,
472 * or -1 if the feature isn't supported.
473 */
474static void Dalvik_dalvik_system_VMDebug_threadCpuTimeNanos(const u4* args,
475    JValue* pResult)
476{
477    jlong result;
478
479#ifdef HAVE_POSIX_CLOCKS
480    struct timespec now;
481    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
482    result = (jlong) (now.tv_sec*1000000000LL + now.tv_nsec);
483#else
484    result = (jlong) -1;
485#endif
486
487    RETURN_LONG(result);
488}
489
490/*
491 * static void dumpHprofData(String fileName, FileDescriptor fd)
492 *
493 * Cause "hprof" data to be dumped.  We can throw an IOException if an
494 * error occurs during file handling.
495 */
496static void Dalvik_dalvik_system_VMDebug_dumpHprofData(const u4* args,
497    JValue* pResult)
498{
499    StringObject* fileNameStr = (StringObject*) args[0];
500    Object* fileDescriptor = (Object*) args[1];
501    char* fileName;
502    int result;
503
504    /*
505     * Only one of these may be NULL.
506     */
507    if (fileNameStr == NULL && fileDescriptor == NULL) {
508        dvmThrowNullPointerException("fileName == null && fd == null");
509        RETURN_VOID();
510    }
511
512    if (fileNameStr != NULL) {
513        fileName = dvmCreateCstrFromString(fileNameStr);
514        if (fileName == NULL) {
515            /* unexpected -- malloc failure? */
516            dvmThrowRuntimeException("malloc failure?");
517            RETURN_VOID();
518        }
519    } else {
520        fileName = strdup("[fd]");
521    }
522
523    int fd = -1;
524    if (fileDescriptor != NULL) {
525        fd = getFileDescriptor(fileDescriptor);
526        if (fd < 0) {
527            free(fileName);
528            RETURN_VOID();
529        }
530    }
531
532    result = hprofDumpHeap(fileName, fd, false);
533    free(fileName);
534
535    if (result != 0) {
536        /* ideally we'd throw something more specific based on actual failure */
537        dvmThrowRuntimeException(
538            "Failure during heap dump; check log output for details");
539        RETURN_VOID();
540    }
541
542    RETURN_VOID();
543}
544
545/*
546 * static void dumpHprofDataDdms()
547 *
548 * Cause "hprof" data to be computed and sent directly to DDMS.
549 */
550static void Dalvik_dalvik_system_VMDebug_dumpHprofDataDdms(const u4* args,
551    JValue* pResult)
552{
553    int result;
554
555    result = hprofDumpHeap("[DDMS]", -1, true);
556
557    if (result != 0) {
558        /* ideally we'd throw something more specific based on actual failure */
559        dvmThrowRuntimeException(
560            "Failure during heap dump; check log output for details");
561        RETURN_VOID();
562    }
563
564    RETURN_VOID();
565}
566
567/*
568 * static boolean cacheRegisterMap(String classAndMethodDescr)
569 *
570 * If the specified class is loaded, and the named method exists, ensure
571 * that the method's register map is ready for use.  If the class/method
572 * cannot be found, nothing happens.
573 *
574 * This can improve the zygote's sharing of compressed register maps.  Do
575 * this after class preloading.
576 *
577 * Returns true if the register map is cached and ready, either as a result
578 * of this call or earlier activity.  Returns false if the class isn't loaded,
579 * if the method couldn't be found, or if the method has no register map.
580 *
581 * (Uncomment logs in dvmGetExpandedRegisterMap0() to gather stats.)
582 */
583static void Dalvik_dalvik_system_VMDebug_cacheRegisterMap(const u4* args,
584    JValue* pResult)
585{
586    StringObject* classAndMethodDescStr = (StringObject*) args[0];
587    ClassObject* clazz;
588    bool result = false;
589
590    if (classAndMethodDescStr == NULL) {
591        dvmThrowNullPointerException("classAndMethodDesc == null");
592        RETURN_VOID();
593    }
594
595    char* classAndMethodDesc = NULL;
596
597    /*
598     * Pick the string apart.  We have a local copy, so just modify it
599     * in place.
600     */
601    classAndMethodDesc = dvmCreateCstrFromString(classAndMethodDescStr);
602
603    char* methodName = strchr(classAndMethodDesc, '.');
604    if (methodName == NULL) {
605        dvmThrowRuntimeException("method name not found in string");
606        RETURN_VOID();
607    }
608    *methodName++ = '\0';
609
610    char* methodDescr = strchr(methodName, ':');
611    if (methodDescr == NULL) {
612        dvmThrowRuntimeException("method descriptor not found in string");
613        RETURN_VOID();
614    }
615    *methodDescr++ = '\0';
616
617    //ALOGD("GOT: %s %s %s", classAndMethodDesc, methodName, methodDescr);
618
619    /*
620     * Find the class, but only if it's already loaded.
621     */
622    clazz = dvmLookupClass(classAndMethodDesc, NULL, false);
623    if (clazz == NULL) {
624        ALOGD("Class %s not found in bootstrap loader", classAndMethodDesc);
625        goto bail;
626    }
627
628    Method* method;
629
630    /*
631     * Find the method, which could be virtual or direct, defined directly
632     * or inherited.
633     */
634    if (methodName[0] == '<') {
635        /*
636         * Constructor or class initializer.  Only need to examine the
637         * "direct" list, and don't need to search up the class hierarchy.
638         */
639        method = dvmFindDirectMethodByDescriptor(clazz, methodName,
640                    methodDescr);
641    } else {
642        /*
643         * Try both lists, and scan up the tree.
644         */
645        method = dvmFindVirtualMethodHierByDescriptor(clazz, methodName,
646                    methodDescr);
647        if (method == NULL) {
648            method = dvmFindDirectMethodHierByDescriptor(clazz, methodName,
649                        methodDescr);
650        }
651    }
652
653    if (method != NULL) {
654        /*
655         * Got it.  See if there's a register map here.
656         */
657        const RegisterMap* pMap;
658        pMap = dvmGetExpandedRegisterMap(method);
659        if (pMap == NULL) {
660            ALOGV("No map for %s.%s %s",
661                classAndMethodDesc, methodName, methodDescr);
662        } else {
663            ALOGV("Found map %s.%s %s",
664                classAndMethodDesc, methodName, methodDescr);
665            result = true;
666        }
667    } else {
668        ALOGV("Unable to find %s.%s %s",
669            classAndMethodDesc, methodName, methodDescr);
670    }
671
672bail:
673    free(classAndMethodDesc);
674    RETURN_BOOLEAN(result);
675}
676
677/*
678 * static void dumpReferenceTables()
679 */
680static void Dalvik_dalvik_system_VMDebug_dumpReferenceTables(const u4* args,
681    JValue* pResult)
682{
683    UNUSED_PARAMETER(args);
684    UNUSED_PARAMETER(pResult);
685
686    ALOGI("--- reference table dump ---");
687    dvmDumpJniReferenceTables();
688    // could dump thread's internalLocalRefTable, probably not useful
689    // ditto for thread's jniMonitorRefTable
690    ALOGI("---");
691    RETURN_VOID();
692}
693
694/*
695 * static void crash()
696 *
697 * Dump the current thread's interpreted stack and abort the VM.  Useful
698 * for seeing both interpreted and native stack traces.
699 *
700 * (Might want to restrict this to debuggable processes as a security
701 * measure, or check SecurityManager.checkExit().)
702 */
703static void Dalvik_dalvik_system_VMDebug_crash(const u4* args,
704    JValue* pResult)
705{
706    UNUSED_PARAMETER(args);
707    UNUSED_PARAMETER(pResult);
708
709    LOGW("Crashing VM on request");
710    dvmDumpThread(dvmThreadSelf(), false);
711    dvmAbort();
712}
713
714/*
715 * static void infopoint(int id)
716 *
717 * Provide a hook for gdb to hang to so that the VM can be stopped when
718 * user-tagged source locations are being executed.
719 */
720static void Dalvik_dalvik_system_VMDebug_infopoint(const u4* args,
721    JValue* pResult)
722{
723    gDvm.nativeDebuggerActive = true;
724
725    ALOGD("VMDebug infopoint %d hit", args[0]);
726
727    gDvm.nativeDebuggerActive = false;
728    RETURN_VOID();
729}
730
731static void Dalvik_dalvik_system_VMDebug_countInstancesOfClass(const u4* args,
732    JValue* pResult)
733{
734    ClassObject* clazz = (ClassObject*)args[0];
735    bool countAssignable = args[1];
736    if (clazz == NULL) {
737        RETURN_LONG(0);
738    }
739    if (countAssignable) {
740        size_t count = dvmCountAssignableInstancesOfClass(clazz);
741        RETURN_LONG((long long)count);
742    } else {
743        size_t count = dvmCountInstancesOfClass(clazz);
744        RETURN_LONG((long long)count);
745    }
746}
747
748const DalvikNativeMethod dvm_dalvik_system_VMDebug[] = {
749    { "getVmFeatureList",           "()[Ljava/lang/String;",
750        Dalvik_dalvik_system_VMDebug_getVmFeatureList },
751    { "getAllocCount",              "(I)I",
752        Dalvik_dalvik_system_VMDebug_getAllocCount },
753    { "resetAllocCount",            "(I)V",
754        Dalvik_dalvik_system_VMDebug_resetAllocCount },
755    { "startAllocCounting",         "()V",
756        Dalvik_dalvik_system_VMDebug_startAllocCounting },
757    { "stopAllocCounting",          "()V",
758        Dalvik_dalvik_system_VMDebug_stopAllocCounting },
759    { "startMethodTracingNative",   "(Ljava/lang/String;Ljava/io/FileDescriptor;II)V",
760        Dalvik_dalvik_system_VMDebug_startMethodTracingNative },
761    { "isMethodTracingActive",      "()Z",
762        Dalvik_dalvik_system_VMDebug_isMethodTracingActive },
763    { "stopMethodTracing",          "()V",
764        Dalvik_dalvik_system_VMDebug_stopMethodTracing },
765    { "startEmulatorTracing",       "()V",
766        Dalvik_dalvik_system_VMDebug_startEmulatorTracing },
767    { "stopEmulatorTracing",        "()V",
768        Dalvik_dalvik_system_VMDebug_stopEmulatorTracing },
769    { "startInstructionCounting",   "()V",
770        Dalvik_dalvik_system_VMDebug_startInstructionCounting },
771    { "stopInstructionCounting",    "()V",
772        Dalvik_dalvik_system_VMDebug_stopInstructionCounting },
773    { "resetInstructionCount",      "()V",
774        Dalvik_dalvik_system_VMDebug_resetInstructionCount },
775    { "getInstructionCount",        "([I)V",
776        Dalvik_dalvik_system_VMDebug_getInstructionCount },
777    { "isDebuggerConnected",        "()Z",
778        Dalvik_dalvik_system_VMDebug_isDebuggerConnected },
779    { "isDebuggingEnabled",         "()Z",
780        Dalvik_dalvik_system_VMDebug_isDebuggingEnabled },
781    { "lastDebuggerActivity",       "()J",
782        Dalvik_dalvik_system_VMDebug_lastDebuggerActivity },
783    { "printLoadedClasses",         "(I)V",
784        Dalvik_dalvik_system_VMDebug_printLoadedClasses },
785    { "getLoadedClassCount",        "()I",
786        Dalvik_dalvik_system_VMDebug_getLoadedClassCount },
787    { "threadCpuTimeNanos",         "()J",
788        Dalvik_dalvik_system_VMDebug_threadCpuTimeNanos },
789    { "dumpHprofData",              "(Ljava/lang/String;Ljava/io/FileDescriptor;)V",
790        Dalvik_dalvik_system_VMDebug_dumpHprofData },
791    { "dumpHprofDataDdms",          "()V",
792        Dalvik_dalvik_system_VMDebug_dumpHprofDataDdms },
793    { "cacheRegisterMap",           "(Ljava/lang/String;)Z",
794        Dalvik_dalvik_system_VMDebug_cacheRegisterMap },
795    { "dumpReferenceTables",        "()V",
796        Dalvik_dalvik_system_VMDebug_dumpReferenceTables },
797    { "crash",                      "()V",
798        Dalvik_dalvik_system_VMDebug_crash },
799    { "infopoint",                 "(I)V",
800        Dalvik_dalvik_system_VMDebug_infopoint },
801    { "countInstancesOfClass",     "(Ljava/lang/Class;Z)J",
802        Dalvik_dalvik_system_VMDebug_countInstancesOfClass },
803    { NULL, NULL, NULL },
804};
805