/* * static void dumpHprofData(String fileName, FileDescriptor fd) * * Cause "hprof" data to be dumped. We can throw an IOException if an * error occurs during file handling. */ static void Dalvik_dalvik_system_VMDebug_dumpHprofData(const u4* args, JValue* pResult) { #ifdef WITH_HPROF StringObject* fileNameStr = (StringObject*) args[0]; Object* fileDescriptor = (Object*) args[1]; char* fileName; int result; /* * Only one of these may be NULL. */ if (fileNameStr == NULL && fileDescriptor == NULL) { dvmThrowException("Ljava/lang/NullPointerException;", NULL); RETURN_VOID(); } if (fileNameStr != NULL) { fileName = dvmCreateCstrFromString(fileNameStr); if (fileName == NULL) { /* unexpected -- malloc failure? */ dvmThrowException("Ljava/lang/RuntimeException;", "malloc failure?"); RETURN_VOID(); } } else { fileName = strdup("[fd]"); } int fd = -1; if (fileDescriptor != NULL) { fd = getFileDescriptor(fileDescriptor); if (fd < 0) RETURN_VOID(); } result = hprofDumpHeap(fileName, fd, false); free(fileName); if (result != 0) { /* ideally we'd throw something more specific based on actual failure */ dvmThrowException("Ljava/lang/RuntimeException;", "Failure during heap dump -- check log output for details"); RETURN_VOID(); } #else dvmThrowException("Ljava/lang/UnsupportedOperationException;", NULL); #endif RETURN_VOID(); }
/* * static void dumpHprofDataDdms() * * Cause "hprof" data to be computed and sent directly to DDMS. */ static void Dalvik_dalvik_system_VMDebug_dumpHprofDataDdms(const u4* args, JValue* pResult) { int result; result = hprofDumpHeap("[DDMS]", -1, true); if (result != 0) { /* ideally we'd throw something more specific based on actual failure */ dvmThrowRuntimeException( "Failure during heap dump; check log output for details"); RETURN_VOID(); } RETURN_VOID(); }
/* * static void dumpHprofDataDdms() * * Cause "hprof" data to be computed and sent directly to DDMS. */ static void Dalvik_dalvik_system_VMDebug_dumpHprofDataDdms(const u4* args, JValue* pResult) { #ifdef WITH_HPROF int result; result = hprofDumpHeap("[DDMS]", -1, true); if (result != 0) { /* ideally we'd throw something more specific based on actual failure */ dvmThrowException("Ljava/lang/RuntimeException;", "Failure during heap dump -- check log output for details"); RETURN_VOID(); } #else dvmThrowException("Ljava/lang/UnsupportedOperationException;", NULL); #endif RETURN_VOID(); }
/* * Sleep in sigwait() until a signal arrives. */ static void* signalCatcherThreadStart(void* arg) { Thread* self = dvmThreadSelf(); sigset_t mask; int cc; UNUSED_PARAMETER(arg); LOGV("Signal catcher thread started (threadid=%d)\n", self->threadId); /* set up mask with signals we want to handle */ sigemptyset(&mask); sigaddset(&mask, SIGQUIT); sigaddset(&mask, SIGUSR1); while (true) { int rcvd; dvmChangeStatus(self, THREAD_VMWAIT); /* * Signals for sigwait() must be blocked but not ignored. We * block signals like SIGQUIT for all threads, so the condition * is met. When the signal hits, we wake up, without any signal * handlers being invoked. * * We want to suspend all other threads, so that it's safe to * traverse their stacks. * * When running under GDB we occasionally return with EINTR (e.g. * when other threads exit). */ loop: cc = sigwait(&mask, &rcvd); if (cc != 0) { if (cc == EINTR) { //LOGV("sigwait: EINTR\n"); goto loop; } assert(!"bad result from sigwait"); } if (!gDvm.haltSignalCatcher) { LOGI("threadid=%d: reacting to signal %d\n", dvmThreadSelf()->threadId, rcvd); } /* set our status to RUNNING, self-suspending if GC in progress */ dvmChangeStatus(self, THREAD_RUNNING); if (gDvm.haltSignalCatcher) break; if (rcvd == SIGQUIT) { dvmSuspendAllThreads(SUSPEND_FOR_STACK_DUMP); dvmDumpLoaderStats("sig"); logThreadStacks(); if (false) { dvmLockMutex(&gDvm.jniGlobalRefLock); dvmDumpReferenceTable(&gDvm.jniGlobalRefTable, "JNI global"); dvmUnlockMutex(&gDvm.jniGlobalRefLock); } //dvmDumpTrackedAllocations(true); dvmResumeAllThreads(SUSPEND_FOR_STACK_DUMP); } else if (rcvd == SIGUSR1) { #if WITH_HPROF LOGI("SIGUSR1 forcing GC and HPROF dump\n"); hprofDumpHeap(NULL); #else LOGI("SIGUSR1 forcing GC (no HPROF)\n"); dvmCollectGarbage(false); #endif } else { LOGE("unexpected signal %d\n", rcvd); } } return NULL; }