OSDN Git Service

Merge "More consistent JNI error reporting."
[android-x86/dalvik.git] / vm / native / dalvik_system_VMDebug.cpp
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  */
34 static 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  */
54 static 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  */
68 enum {
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  */
106 static 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  */
141 static 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  */
155 static 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  */
167 static 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  */
216 static 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  */
235 static 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  */
282 static 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  */
295 static 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  */
309 static 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  */
323 static 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  */
337 static 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  */
350 static 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  */
364 static 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  */
375 static 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  */
385 static 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  */
401 static 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  */
430 static 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  */
443 static 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  */
458 static 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  */
474 static 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  */
496 static 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  */
550 static 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  */
583 static 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
672 bail:
673     free(classAndMethodDesc);
674     RETURN_BOOLEAN(result);
675 }
676
677 /*
678  * static void dumpReferenceTables()
679  */
680 static 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  */
703 static void Dalvik_dalvik_system_VMDebug_crash(const u4* args,
704     JValue* pResult)
705 {
706     UNUSED_PARAMETER(args);
707     UNUSED_PARAMETER(pResult);
708
709     ALOGW("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  */
720 static 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
731 static 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
748 const 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 };