/* * public native void gcSoftReferences() * * Does a GC and forces collection of SoftReferences that are * not strongly-reachable. */ static void Dalvik_dalvik_system_VMRuntime_gcSoftReferences(const u4* args, JValue* pResult) { dvmCollectGarbage(true); RETURN_VOID(); }
/* * public void gc() * * Initiate a gc. */ static void Dalvik_java_lang_Runtime_gc(const u4* args, JValue* pResult) { UNUSED_PARAMETER(args); dvmCollectGarbage(false); 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; }
/* * Respond to a SIGUSR1 by forcing a GC. */ static void handleSigUsr1() { ALOGI("SIGUSR1 forcing GC (no HPROF)"); dvmCollectGarbage(); }