// Set to true to always determine the non-debuggable classes even if we would not allow a debugger // to actually attach. staticbool kAlwaysCollectNonDebuggableClasses =
RegisterRuntimeDebugFlag(&kAlwaysCollectNonDebuggableClasses);
using android::base::StringPrintf;
class ClassSet { public: // The number of classes we reasonably expect to have to look at. Realistically the number is more // ~10 but there is little harm in having some extra. static constexpr int kClassSetCapacity = 100;
bool VisitFrame() override REQUIRES(Locks::mutator_lock_) { if (GetMethod()->IsRuntimeMethod()) { returntrue;
}
class_set_->AddClass(GetMethod()->GetDeclaringClass()); if (kIsDebugBuild) {
LOG(INFO) << GetMethod()->GetDeclaringClass()->PrettyClass()
<< " might not be fully debuggable/deoptimizable due to "
<< GetMethod()->PrettyMethod() << " appearing on the stack during zygote fork.";
} returntrue;
}
// bits to shift (flags & HIDDEN_API_ENFORCEMENT_POLICY_MASK) by to get a value // corresponding to hiddenapi::EnforcementPolicy
API_ENFORCEMENT_POLICY_SHIFT = CTZ(HIDDEN_API_ENFORCEMENT_POLICY_MASK),
};
static uint32_t EnableDebugFeatures(uint32_t runtime_flags) {
Runtime* const runtime = Runtime::Current(); if ((runtime_flags & DEBUG_ENABLE_CHECKJNI) != 0) {
JavaVMExt* vm = runtime->GetJavaVM(); if (!vm->IsCheckJniEnabled()) {
LOG(INFO) << "Late-enabling -Xcheck:jni";
vm->SetCheckJniEnabled(true); // This is the only thread that's running at this point and the above call sets // the CheckJNI flag in the corresponding `JniEnvExt`.
DCHECK(Thread::Current()->GetJniEnv()->IsCheckJniEnabled());
} else {
LOG(INFO) << "Not late-enabling -Xcheck:jni (already on)";
}
runtime_flags &= ~DEBUG_ENABLE_CHECKJNI;
}
if ((runtime_flags & DEBUG_GENERATE_MINI_DEBUG_INFO) != 0) { // Generate native minimal debug information to allow backtracing.
runtime->AddCompilerOption("--generate-mini-debug-info");
runtime_flags &= ~DEBUG_GENERATE_MINI_DEBUG_INFO;
}
if ((runtime_flags & DEBUG_GENERATE_DEBUG_INFO) != 0) { // Generate all native debug information we can (e.g. line-numbers).
runtime->AddCompilerOption("--generate-debug-info");
runtime_flags &= ~DEBUG_GENERATE_DEBUG_INFO;
}
staticvoid ZygoteHooks_nativePostForkSystemServer([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass klass,
jint runtime_flags) { // Reload the current flags first. In case we need to take actions based on them.
Runtime::Current()->ReloadAllFlags(__FUNCTION__);
// Set the runtime state as the first thing, in case JIT and other services // start querying it.
Runtime::Current()->SetAsSystemServer();
// This JIT code cache for system server is created whilst the runtime is still single threaded. // System server has a window where it can create executable pages for this purpose, but this is // turned off after this hook. Consequently, the only JIT mode supported is the dual-view JIT // where one mapping is R->RW and the other is RX. Single view requires RX->RWX->RX. if (Runtime::Current()->GetJit() != nullptr) {
Runtime::Current()->GetJit()->GetCodeCache()->PostForkChildAction( /* is_system_server= */ true, /* is_zygote= */ false);
} // Enable profiling if required based on the flags. This is done here instead of in // nativePostForkChild since nativePostForkChild is called after loading the system server oat // files. bool profile_system_server = (runtime_flags & PROFILE_SYSTEM_SERVER) == PROFILE_SYSTEM_SERVER;
Runtime::Current()->GetJITOptions()->SetSaveProfilingInfo(profile_system_server);
}
staticvoid ZygoteHooks_nativePostForkChild(JNIEnv* env,
jclass,
jlong token,
jint runtime_flags,
jboolean is_system_server,
jboolean is_zygote,
jstring instruction_set) {
DCHECK(!(is_system_server && is_zygote)); // Reload the current flags first. In case we need to take any updated actions.
Runtime::Current()->ReloadAllFlags(__FUNCTION__); // Then, set the runtime state, in case JIT and other services // start querying it.
Runtime::Current()->SetAsZygoteChild(is_system_server, is_zygote);
Thread* thread = reinterpret_cast<Thread*>(token); // Our system thread ID, etc, has changed so reset Thread state.
thread->InitAfterFork();
runtime_flags = EnableDebugFeatures(runtime_flags);
hiddenapi::EnforcementPolicy api_enforcement_policy = hiddenapi::EnforcementPolicy::kDisabled;
if (runtime_flags != 0) {
LOG(ERROR) << StringPrintf("Unknown bits set in runtime_flags: %#x", runtime_flags);
}
runtime->GetHeap()->PostForkChildAction(thread);
if (!is_zygote) { // Setup an app startup complete task in case the app doesn't notify it // through VMRuntime::notifyStartupCompleted. static constexpr uint64_t kMaxAppStartupTimeNs = MsToNs(5000); // 5 seconds
runtime->GetHeap()->AddHeapTask(new StartupCompletedTask(NanoTime() + kMaxAppStartupTimeNs));
}
if (runtime->GetJit() != nullptr) { if (!is_system_server) { // System server already called the JIT cache post fork action in `nativePostForkSystemServer`.
runtime->GetJit()->GetCodeCache()->PostForkChildAction( /* is_system_server= */ false, is_zygote);
} // This must be called after EnableDebugFeatures.
runtime->GetJit()->PostForkChildAction(is_system_server, is_zygote);
}
// Update tracing. if (Trace::GetMethodTracingMode() != TracingMode::kTracingInactive) {
TraceOutputMode output_mode = Trace::GetOutputMode();
Trace::TraceMode trace_mode = Trace::GetMode();
size_t buffer_size = Trace::GetBufferSize(); int flags = Trace::GetFlags(); int interval = Trace::GetIntervalInMillis();
// Just drop it.
Trace::Abort();
// Only restart if it was streaming mode. // TODO: Expose buffer size, so we can also do file mode. if (output_mode == TraceOutputMode::kStreaming) { static constexpr size_t kMaxProcessNameLength = 100; char name_buf[kMaxProcessNameLength] = {}; int rc = pthread_getname_np(pthread_self(), name_buf, kMaxProcessNameLength);
std::string proc_name;
if (rc == 0) { // On success use the pthread name.
proc_name = name_buf;
}
if (proc_name.empty() || proc_name == "zygote" || proc_name == "zygote64") { // Either no process name, or the name hasn't been changed, yet. Just use pid.
pid_t pid = getpid();
proc_name = StringPrintf("%u", static_cast<uint32_t>(pid));
}
bool do_hidden_api_checks = api_enforcement_policy != hiddenapi::EnforcementPolicy::kDisabled;
DCHECK(!(is_system_server && do_hidden_api_checks))
<< "SystemServer should be forked with EnforcementPolicy::kDisable";
DCHECK(!(is_zygote && do_hidden_api_checks))
<< "Child zygote processes should be forked with EnforcementPolicy::kDisable";
runtime->SetHiddenApiEnforcementPolicy(api_enforcement_policy);
runtime->SetDedupeHiddenApiWarnings(true); if (api_enforcement_policy != hiddenapi::EnforcementPolicy::kDisabled &&
runtime->GetHiddenApiEventLogSampleRate() != 0) { // Hidden API checks are enabled, and we are sampling access for the event log. Initialize the // random seed, to ensure the sampling is actually random. We do this post-fork, as doing it // pre-fork would result in the same sequence for every forked process.
std::srand(static_cast<uint32_t>(NanoTime()));
}
static jboolean ZygoteHooks_nativeZygoteLongSuspendOk([[maybe_unused]] JNIEnv* env,
[[maybe_unused]] jclass klass) { // Indefinite thread suspensions are not OK if we're supposed to be JIT-compiling for other // processes. We only care about JIT compilation that affects other processes. The zygote // itself doesn't run appreciable amounts of Java code when running single-threaded, so // suspending the JIT in non-jit-zygote mode is OK. // TODO: Make this potentially return true once we're done with JIT compilation in JIT Zygote. // Only called in zygote. Thus static is OK here. staticbool isJitZygote = jit::Jit::InZygoteUsingJit(); staticbool explicitlyDisabled = Runtime::Current()->IsJavaZygoteForkLoopRequired(); return (isJitZygote || explicitlyDisabled) ? JNI_FALSE : JNI_TRUE;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.