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