2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * dalvik.system.VMDebug
21 #include "native/InternalNativePriv.h"
22 #include "hprof/Hprof.h"
30 * Extracts the fd from a FileDescriptor object.
32 * If an error is encountered, or the extracted descriptor is numerically
33 * invalid, this returns -1 with an exception raised.
35 static int getFileDescriptor(Object* obj)
38 assert(strcmp(obj->clazz->descriptor, "Ljava/io/FileDescriptor;") == 0);
40 InstField* field = dvmFindInstanceField(obj->clazz, "descriptor", "I");
42 dvmThrowException("Ljava/lang/NoSuchFieldException;",
43 "No FileDescriptor.descriptor field");
47 int fd = dvmGetFieldInt(obj, field->byteOffset);
49 dvmThrowExceptionFmt("Ljava/lang/RuntimeException;",
50 "Invalid file descriptor");
58 * Convert an array of char* into a String[].
60 * Returns NULL on failure, with an exception raised.
62 static ArrayObject* convertStringArray(char** strings, size_t count)
64 Thread* self = dvmThreadSelf();
67 * Allocate an array to hold the String objects.
69 ClassObject* stringArrayClass =
70 dvmFindArrayClass("[Ljava/lang/String;", NULL);
71 if (stringArrayClass == NULL) {
72 /* shouldn't happen */
73 LOGE("Unable to find [Ljava/lang/String;\n");
77 ArrayObject* stringArray =
78 dvmAllocArrayByClass(stringArrayClass, count, ALLOC_DEFAULT);
79 if (stringArray == NULL) {
81 LOGD("Failed allocating array of %d strings\n", count);
82 assert(dvmCheckException(self));
87 * Create the individual String objects and add them to the array.
90 for (i = 0; i < count; i++) {
92 (Object *)dvmCreateStringFromCstr(strings[i]);
94 /* probably OOM; drop out now */
95 assert(dvmCheckException(self));
96 dvmReleaseTrackedAlloc((Object*)stringArray, self);
99 dvmSetObjectArrayElement(stringArray, i, str);
100 /* stored in tracked array, okay to release */
101 dvmReleaseTrackedAlloc(str, self);
104 dvmReleaseTrackedAlloc((Object*)stringArray, self);
109 * static String[] getVmFeatureList()
111 * Return a set of strings describing available VM features (this is chiefly
112 * of interest to DDMS). Some features may be controlled by compile-time
113 * or command-line flags.
115 static void Dalvik_dalvik_system_VMDebug_getVmFeatureList(const u4* args,
118 static const int MAX_FEATURE_COUNT = 10;
119 char* features[MAX_FEATURE_COUNT];
122 /* VM responds to DDMS method profiling requests */
123 features[idx++] = "method-trace-profiling";
124 features[idx++] = "method-trace-profiling-streaming";
125 /* VM responds to DDMS heap dump requests */
126 features[idx++] = "hprof-heap-dump";
127 features[idx++] = "hprof-heap-dump-streaming";
129 assert(idx <= MAX_FEATURE_COUNT);
131 LOGV("+++ sending up %d features\n", idx);
132 ArrayObject* arrayObj = convertStringArray(features, idx);
133 RETURN_PTR(arrayObj); /* will be null on OOM */
137 /* These must match the values in dalvik.system.VMDebug.
140 KIND_ALLOCATED_OBJECTS = 1<<0,
141 KIND_ALLOCATED_BYTES = 1<<1,
142 KIND_FREED_OBJECTS = 1<<2,
143 KIND_FREED_BYTES = 1<<3,
144 KIND_GC_INVOCATIONS = 1<<4,
145 KIND_CLASS_INIT_COUNT = 1<<5,
146 KIND_CLASS_INIT_TIME = 1<<6,
148 /* These values exist for backward compatibility. */
149 KIND_EXT_ALLOCATED_OBJECTS = 1<<12,
150 KIND_EXT_ALLOCATED_BYTES = 1<<13,
151 KIND_EXT_FREED_OBJECTS = 1<<14,
152 KIND_EXT_FREED_BYTES = 1<<15,
154 KIND_GLOBAL_ALLOCATED_OBJECTS = KIND_ALLOCATED_OBJECTS,
155 KIND_GLOBAL_ALLOCATED_BYTES = KIND_ALLOCATED_BYTES,
156 KIND_GLOBAL_FREED_OBJECTS = KIND_FREED_OBJECTS,
157 KIND_GLOBAL_FREED_BYTES = KIND_FREED_BYTES,
158 KIND_GLOBAL_GC_INVOCATIONS = KIND_GC_INVOCATIONS,
159 KIND_GLOBAL_CLASS_INIT_COUNT = KIND_CLASS_INIT_COUNT,
160 KIND_GLOBAL_CLASS_INIT_TIME = KIND_CLASS_INIT_TIME,
162 KIND_THREAD_ALLOCATED_OBJECTS = KIND_ALLOCATED_OBJECTS << 16,
163 KIND_THREAD_ALLOCATED_BYTES = KIND_ALLOCATED_BYTES << 16,
164 KIND_THREAD_FREED_OBJECTS = KIND_FREED_OBJECTS << 16,
165 KIND_THREAD_FREED_BYTES = KIND_FREED_BYTES << 16,
167 KIND_THREAD_GC_INVOCATIONS = KIND_GC_INVOCATIONS << 16,
169 // TODO: failedAllocCount, failedAllocSize
172 #define KIND_ALL_COUNTS 0xffffffff
175 * Zero out the specified fields.
177 static void clearAllocProfStateFields(AllocProfState *allocProf,
180 if (kinds & KIND_ALLOCATED_OBJECTS) {
181 allocProf->allocCount = 0;
183 if (kinds & KIND_ALLOCATED_BYTES) {
184 allocProf->allocSize = 0;
186 if (kinds & KIND_FREED_OBJECTS) {
187 allocProf->freeCount = 0;
189 if (kinds & KIND_FREED_BYTES) {
190 allocProf->freeSize = 0;
192 if (kinds & KIND_GC_INVOCATIONS) {
193 allocProf->gcCount = 0;
195 if (kinds & KIND_CLASS_INIT_COUNT) {
196 allocProf->classInitCount = 0;
198 if (kinds & KIND_CLASS_INIT_TIME) {
199 allocProf->classInitTime = 0;
204 * static void startAllocCounting()
206 * Reset the counters and enable counting.
208 * TODO: this currently only resets the per-thread counters for the current
209 * thread. If we actually start using the per-thread counters we'll
210 * probably want to fix this.
212 static void Dalvik_dalvik_system_VMDebug_startAllocCounting(const u4* args,
215 UNUSED_PARAMETER(args);
217 clearAllocProfStateFields(&gDvm.allocProf, KIND_ALL_COUNTS);
218 clearAllocProfStateFields(&dvmThreadSelf()->allocProf, KIND_ALL_COUNTS);
219 dvmStartAllocCounting();
224 * public static void stopAllocCounting()
226 static void Dalvik_dalvik_system_VMDebug_stopAllocCounting(const u4* args,
229 UNUSED_PARAMETER(args);
231 dvmStopAllocCounting();
236 * private static int getAllocCount(int kind)
238 static void Dalvik_dalvik_system_VMDebug_getAllocCount(const u4* args,
241 AllocProfState *allocProf;
242 unsigned int kind = args[0];
243 if (kind < (1<<16)) {
244 allocProf = &gDvm.allocProf;
246 allocProf = &dvmThreadSelf()->allocProf;
250 case KIND_ALLOCATED_OBJECTS:
251 pResult->i = allocProf->allocCount;
253 case KIND_ALLOCATED_BYTES:
254 pResult->i = allocProf->allocSize;
256 case KIND_FREED_OBJECTS:
257 pResult->i = allocProf->freeCount;
259 case KIND_FREED_BYTES:
260 pResult->i = allocProf->freeSize;
262 case KIND_GC_INVOCATIONS:
263 pResult->i = allocProf->gcCount;
265 case KIND_CLASS_INIT_COUNT:
266 pResult->i = allocProf->classInitCount;
268 case KIND_CLASS_INIT_TIME:
269 /* convert nsec to usec, reduce to 32 bits */
270 pResult->i = (int) (allocProf->classInitTime / 1000);
272 case KIND_EXT_ALLOCATED_OBJECTS:
273 case KIND_EXT_ALLOCATED_BYTES:
274 case KIND_EXT_FREED_OBJECTS:
275 case KIND_EXT_FREED_BYTES:
276 pResult->i = 0; /* backward compatibility */
285 * public static void resetAllocCount(int kinds)
287 static void Dalvik_dalvik_system_VMDebug_resetAllocCount(const u4* args,
290 unsigned int kinds = args[0];
291 clearAllocProfStateFields(&gDvm.allocProf, kinds & 0xffff);
292 clearAllocProfStateFields(&dvmThreadSelf()->allocProf, kinds >> 16);
297 * static void startMethodTracingNative(String traceFileName,
298 * FileDescriptor fd, int bufferSize, int flags)
300 * Start method trace profiling.
302 * If both "traceFileName" and "fd" are null, the result will be sent
303 * directly to DDMS. (The non-DDMS versions of the calls are expected
304 * to enforce non-NULL filenames.)
306 static void Dalvik_dalvik_system_VMDebug_startMethodTracingNative(const u4* args,
309 StringObject* traceFileStr = (StringObject*) args[0];
310 Object* traceFd = (Object*) args[1];
311 int bufferSize = args[2];
314 if (bufferSize == 0) {
315 // Default to 8MB per the documentation.
316 bufferSize = 8 * 1024 * 1024;
319 if (bufferSize < 1024) {
320 dvmThrowException("Ljava/lang/IllegalArgumentException;", NULL);
324 char* traceFileName = NULL;
325 if (traceFileStr != NULL)
326 traceFileName = dvmCreateCstrFromString(traceFileStr);
329 if (traceFd != NULL) {
330 int origFd = getFileDescriptor(traceFd);
336 dvmThrowExceptionFmt("Ljava/lang/RuntimeException;",
337 "dup(%d) failed: %s", origFd, strerror(errno));
342 dvmMethodTraceStart(traceFileName != NULL ? traceFileName : "[DDMS]",
343 fd, bufferSize, flags, (traceFileName == NULL && fd == -1));
349 * static boolean isMethodTracingActive()
351 * Determine whether method tracing is currently active.
353 static void Dalvik_dalvik_system_VMDebug_isMethodTracingActive(const u4* args,
356 UNUSED_PARAMETER(args);
358 RETURN_BOOLEAN(dvmIsMethodTraceActive());
362 * static void stopMethodTracing()
364 * Stop method tracing.
366 static void Dalvik_dalvik_system_VMDebug_stopMethodTracing(const u4* args,
369 UNUSED_PARAMETER(args);
371 dvmMethodTraceStop();
376 * static void startEmulatorTracing()
378 * Start sending method trace info to the emulator.
380 static void Dalvik_dalvik_system_VMDebug_startEmulatorTracing(const u4* args,
383 UNUSED_PARAMETER(args);
385 dvmEmulatorTraceStart();
390 * static void stopEmulatorTracing()
392 * Start sending method trace info to the emulator.
394 static void Dalvik_dalvik_system_VMDebug_stopEmulatorTracing(const u4* args,
397 UNUSED_PARAMETER(args);
399 dvmEmulatorTraceStop();
404 * static boolean isDebuggerConnected()
406 * Returns "true" if a debugger is attached.
408 static void Dalvik_dalvik_system_VMDebug_isDebuggerConnected(const u4* args,
411 UNUSED_PARAMETER(args);
413 RETURN_BOOLEAN(dvmDbgIsDebuggerConnected());
417 * static boolean isDebuggingEnabled()
419 * Returns "true" if debugging is enabled.
421 static void Dalvik_dalvik_system_VMDebug_isDebuggingEnabled(const u4* args,
424 UNUSED_PARAMETER(args);
426 RETURN_BOOLEAN(gDvm.jdwpConfigured);
430 * static long lastDebuggerActivity()
432 * Returns the time, in msec, since we last had an interaction with the
433 * debugger (send or receive).
435 static void Dalvik_dalvik_system_VMDebug_lastDebuggerActivity(const u4* args,
438 UNUSED_PARAMETER(args);
440 RETURN_LONG(dvmDbgLastDebuggerActivity());
444 * static void startInstructionCounting()
446 static void Dalvik_dalvik_system_VMDebug_startInstructionCounting(const u4* args,
449 dvmStartInstructionCounting();
454 * static void stopInstructionCounting()
456 static void Dalvik_dalvik_system_VMDebug_stopInstructionCounting(const u4* args,
459 dvmStopInstructionCounting();
464 * static boolean getInstructionCount(int[] counts)
466 * Grab a copy of the global instruction count array.
468 * Since the instruction counts aren't synchronized, we use sched_yield
469 * to improve our chances of finishing without contention. (Only makes
470 * sense on a uniprocessor.)
472 static void Dalvik_dalvik_system_VMDebug_getInstructionCount(const u4* args,
475 ArrayObject* countArray = (ArrayObject*) args[0];
477 if (countArray != NULL) {
478 int* storage = (int*) countArray->contents;
479 u4 length = countArray->length;
482 * Ensure that we copy at most kNumPackedOpcodes
483 * elements, but no more than the length of the given array.
485 if (length > kNumPackedOpcodes) {
486 length = kNumPackedOpcodes;
490 memcpy(storage, gDvm.executedInstrCounts, length * sizeof(int));
497 * static boolean resetInstructionCount()
499 * Reset the instruction count array.
501 static void Dalvik_dalvik_system_VMDebug_resetInstructionCount(const u4* args,
505 memset(gDvm.executedInstrCounts, 0, kNumPackedOpcodes * sizeof(int));
510 * static void printLoadedClasses(int flags)
512 * Dump the list of loaded classes.
514 static void Dalvik_dalvik_system_VMDebug_printLoadedClasses(const u4* args,
519 dvmDumpAllClasses(flags);
525 * static int getLoadedClassCount()
527 * Return the number of loaded classes
529 static void Dalvik_dalvik_system_VMDebug_getLoadedClassCount(const u4* args,
534 UNUSED_PARAMETER(args);
536 count = dvmGetNumLoadedClasses();
542 * Returns the thread-specific CPU-time clock value for the current thread,
543 * or -1 if the feature isn't supported.
545 static void Dalvik_dalvik_system_VMDebug_threadCpuTimeNanos(const u4* args,
550 #ifdef HAVE_POSIX_CLOCKS
552 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
553 result = (jlong) (now.tv_sec*1000000000LL + now.tv_nsec);
562 * static void dumpHprofData(String fileName, FileDescriptor fd)
564 * Cause "hprof" data to be dumped. We can throw an IOException if an
565 * error occurs during file handling.
567 static void Dalvik_dalvik_system_VMDebug_dumpHprofData(const u4* args,
570 StringObject* fileNameStr = (StringObject*) args[0];
571 Object* fileDescriptor = (Object*) args[1];
576 * Only one of these may be NULL.
578 if (fileNameStr == NULL && fileDescriptor == NULL) {
579 dvmThrowException("Ljava/lang/NullPointerException;", NULL);
583 if (fileNameStr != NULL) {
584 fileName = dvmCreateCstrFromString(fileNameStr);
585 if (fileName == NULL) {
586 /* unexpected -- malloc failure? */
587 dvmThrowException("Ljava/lang/RuntimeException;", "malloc failure?");
591 fileName = strdup("[fd]");
595 if (fileDescriptor != NULL) {
596 fd = getFileDescriptor(fileDescriptor);
603 result = hprofDumpHeap(fileName, fd, false);
607 /* ideally we'd throw something more specific based on actual failure */
608 dvmThrowException("Ljava/lang/RuntimeException;",
609 "Failure during heap dump -- check log output for details");
617 * static void dumpHprofDataDdms()
619 * Cause "hprof" data to be computed and sent directly to DDMS.
621 static void Dalvik_dalvik_system_VMDebug_dumpHprofDataDdms(const u4* args,
626 result = hprofDumpHeap("[DDMS]", -1, true);
629 /* ideally we'd throw something more specific based on actual failure */
630 dvmThrowException("Ljava/lang/RuntimeException;",
631 "Failure during heap dump -- check log output for details");
639 * static boolean cacheRegisterMap(String classAndMethodDescr)
641 * If the specified class is loaded, and the named method exists, ensure
642 * that the method's register map is ready for use. If the class/method
643 * cannot be found, nothing happens.
645 * This can improve the zygote's sharing of compressed register maps. Do
646 * this after class preloading.
648 * Returns true if the register map is cached and ready, either as a result
649 * of this call or earlier activity. Returns false if the class isn't loaded,
650 * if the method couldn't be found, or if the method has no register map.
652 * (Uncomment logs in dvmGetExpandedRegisterMap0() to gather stats.)
654 static void Dalvik_dalvik_system_VMDebug_cacheRegisterMap(const u4* args,
657 StringObject* classAndMethodDescStr = (StringObject*) args[0];
661 if (classAndMethodDescStr == NULL) {
662 dvmThrowException("Ljava/lang/NullPointerException;", NULL);
666 char* classAndMethodDesc = NULL;
669 * Pick the string apart. We have a local copy, so just modify it
672 classAndMethodDesc = dvmCreateCstrFromString(classAndMethodDescStr);
674 char* methodName = strchr(classAndMethodDesc, '.');
675 if (methodName == NULL) {
676 dvmThrowException("Ljava/lang/RuntimeException;",
677 "method name not found in string");
680 *methodName++ = '\0';
682 char* methodDescr = strchr(methodName, ':');
683 if (methodDescr == NULL) {
684 dvmThrowException("Ljava/lang/RuntimeException;",
685 "method descriptor not found in string");
688 *methodDescr++ = '\0';
690 //LOGD("GOT: %s %s %s\n", classAndMethodDesc, methodName, methodDescr);
693 * Find the class, but only if it's already loaded.
695 clazz = dvmLookupClass(classAndMethodDesc, NULL, false);
697 LOGD("Class %s not found in bootstrap loader\n", classAndMethodDesc);
704 * Find the method, which could be virtual or direct, defined directly
707 if (methodName[0] == '<') {
709 * Constructor or class initializer. Only need to examine the
710 * "direct" list, and don't need to search up the class hierarchy.
712 method = dvmFindDirectMethodByDescriptor(clazz, methodName,
716 * Try both lists, and scan up the tree.
718 method = dvmFindVirtualMethodHierByDescriptor(clazz, methodName,
720 if (method == NULL) {
721 method = dvmFindDirectMethodHierByDescriptor(clazz, methodName,
726 if (method != NULL) {
728 * Got it. See if there's a register map here.
730 const RegisterMap* pMap;
731 pMap = dvmGetExpandedRegisterMap(method);
733 LOGV("No map for %s.%s %s\n",
734 classAndMethodDesc, methodName, methodDescr);
736 LOGV("Found map %s.%s %s\n",
737 classAndMethodDesc, methodName, methodDescr);
741 LOGV("Unable to find %s.%s %s\n",
742 classAndMethodDesc, methodName, methodDescr);
746 free(classAndMethodDesc);
747 RETURN_BOOLEAN(result);
751 * static void dumpReferenceTables()
753 static void Dalvik_dalvik_system_VMDebug_dumpReferenceTables(const u4* args,
756 UNUSED_PARAMETER(args);
757 UNUSED_PARAMETER(pResult);
759 LOGI("--- reference table dump ---\n");
760 dvmDumpJniReferenceTables();
761 // could dump thread's internalLocalRefTable, probably not useful
762 // ditto for thread's jniMonitorRefTable
768 * static void crash()
770 * Dump the current thread's interpreted stack and abort the VM. Useful
771 * for seeing both interpreted and native stack traces.
773 * (Might want to restrict this to debuggable processes as a security
774 * measure, or check SecurityManager.checkExit().)
776 static void Dalvik_dalvik_system_VMDebug_crash(const u4* args,
779 UNUSED_PARAMETER(args);
780 UNUSED_PARAMETER(pResult);
782 LOGW("Crashing VM on request\n");
783 dvmDumpThread(dvmThreadSelf(), false);
788 * static void infopoint(int id)
790 * Provide a hook for gdb to hang to so that the VM can be stopped when
791 * user-tagged source locations are being executed.
793 static void Dalvik_dalvik_system_VMDebug_infopoint(const u4* args,
796 gDvm.nativeDebuggerActive = true;
798 LOGD("VMDebug infopoint %d hit", args[0]);
800 gDvm.nativeDebuggerActive = false;
804 static void Dalvik_dalvik_system_VMDebug_countInstancesOfClass(const u4* args,
807 ClassObject* clazz = (ClassObject*)args[0];
808 bool countAssignable = args[1];
812 if (countAssignable) {
813 size_t count = dvmCountAssignableInstancesOfClass(clazz);
814 RETURN_LONG((long long)count);
816 size_t count = dvmCountInstancesOfClass(clazz);
817 RETURN_LONG((long long)count);
821 const DalvikNativeMethod dvm_dalvik_system_VMDebug[] = {
822 { "getVmFeatureList", "()[Ljava/lang/String;",
823 Dalvik_dalvik_system_VMDebug_getVmFeatureList },
824 { "getAllocCount", "(I)I",
825 Dalvik_dalvik_system_VMDebug_getAllocCount },
826 { "resetAllocCount", "(I)V",
827 Dalvik_dalvik_system_VMDebug_resetAllocCount },
828 { "startAllocCounting", "()V",
829 Dalvik_dalvik_system_VMDebug_startAllocCounting },
830 { "stopAllocCounting", "()V",
831 Dalvik_dalvik_system_VMDebug_stopAllocCounting },
832 { "startMethodTracingNative", "(Ljava/lang/String;Ljava/io/FileDescriptor;II)V",
833 Dalvik_dalvik_system_VMDebug_startMethodTracingNative },
834 { "isMethodTracingActive", "()Z",
835 Dalvik_dalvik_system_VMDebug_isMethodTracingActive },
836 { "stopMethodTracing", "()V",
837 Dalvik_dalvik_system_VMDebug_stopMethodTracing },
838 { "startEmulatorTracing", "()V",
839 Dalvik_dalvik_system_VMDebug_startEmulatorTracing },
840 { "stopEmulatorTracing", "()V",
841 Dalvik_dalvik_system_VMDebug_stopEmulatorTracing },
842 { "startInstructionCounting", "()V",
843 Dalvik_dalvik_system_VMDebug_startInstructionCounting },
844 { "stopInstructionCounting", "()V",
845 Dalvik_dalvik_system_VMDebug_stopInstructionCounting },
846 { "resetInstructionCount", "()V",
847 Dalvik_dalvik_system_VMDebug_resetInstructionCount },
848 { "getInstructionCount", "([I)V",
849 Dalvik_dalvik_system_VMDebug_getInstructionCount },
850 { "isDebuggerConnected", "()Z",
851 Dalvik_dalvik_system_VMDebug_isDebuggerConnected },
852 { "isDebuggingEnabled", "()Z",
853 Dalvik_dalvik_system_VMDebug_isDebuggingEnabled },
854 { "lastDebuggerActivity", "()J",
855 Dalvik_dalvik_system_VMDebug_lastDebuggerActivity },
856 { "printLoadedClasses", "(I)V",
857 Dalvik_dalvik_system_VMDebug_printLoadedClasses },
858 { "getLoadedClassCount", "()I",
859 Dalvik_dalvik_system_VMDebug_getLoadedClassCount },
860 { "threadCpuTimeNanos", "()J",
861 Dalvik_dalvik_system_VMDebug_threadCpuTimeNanos },
862 { "dumpHprofData", "(Ljava/lang/String;Ljava/io/FileDescriptor;)V",
863 Dalvik_dalvik_system_VMDebug_dumpHprofData },
864 { "dumpHprofDataDdms", "()V",
865 Dalvik_dalvik_system_VMDebug_dumpHprofDataDdms },
866 { "cacheRegisterMap", "(Ljava/lang/String;)Z",
867 Dalvik_dalvik_system_VMDebug_cacheRegisterMap },
868 { "dumpReferenceTables", "()V",
869 Dalvik_dalvik_system_VMDebug_dumpReferenceTables },
871 Dalvik_dalvik_system_VMDebug_crash },
872 { "infopoint", "(I)V",
873 Dalvik_dalvik_system_VMDebug_infopoint },
874 { "countInstancesOfClass", "(Ljava/lang/Class;Z)J",
875 Dalvik_dalvik_system_VMDebug_countInstancesOfClass },
876 { NULL, NULL, NULL },