/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ART_RUNTIME_RUNTIME_H_ #define ART_RUNTIME_RUNTIME_H_ #include #include #include #include #include #include #include #include #include #include "app_info.h" #include "base/locks.h" #include "base/macros.h" #include "base/mem_map.h" #include "base/metrics/metrics.h" #include "base/os.h" #include "base/unix_file/fd_file.h" #include "compat_framework.h" #include "deoptimization_kind.h" #include "dex/dex_file_types.h" #include "experimental_flags.h" #include "gc_root.h" #include "instrumentation.h" #include "jdwp_provider.h" #include "jni/jni_id_manager.h" #include "jni_id_type.h" #include "metrics/reporter.h" #include "obj_ptr.h" #include "offsets.h" #include "process_state.h" #include "quick/quick_method_frame_info.h" #include "reflective_value_visitor.h" #include "runtime_stats.h" namespace art HIDDEN { namespace gc { class AbstractSystemWeakHolder; class Heap; } // namespace gc namespace hiddenapi { enum class EnforcementPolicy; } // namespace hiddenapi namespace jit { class Jit; class JitCodeCache; class JitOptions; } // namespace jit namespace jni { class SmallLrtAllocator; } // namespace jni namespace mirror { class Array; class ClassLoader; class DexCache; template class ObjectArray; template class PrimitiveArray; using ByteArray = PrimitiveArray; class String; class Throwable; } // namespace mirror namespace ti { class Agent; class AgentSpec; } // namespace ti namespace verifier { class MethodVerifier; enum class VerifyMode : int8_t; } // namespace verifier class ArenaPool; class ArtMethod; enum class CalleeSaveType: uint32_t; class ClassLinker; class CompilerCallbacks; class Dex2oatImageTest; class DexFile; enum class InstructionSet; class InternTable; class IsMarkedVisitor; class JavaVMExt; class LinearAlloc; class MonitorList; class MonitorPool; class NullPointerHandler; class OatFileAssistantTest; class OatFileManager; class Plugin; struct RuntimeArgumentMap; class RuntimeCallbacks; class SignalCatcher; class StackOverflowHandler; class SuspensionHandler; class ThreadList; class ThreadPool; class Trace; struct TraceConfig; using RuntimeOptions = std::vector>; class Runtime { public: // Parse raw runtime options. EXPORT static bool ParseOptions(const RuntimeOptions& raw_options, bool ignore_unrecognized, RuntimeArgumentMap* runtime_options); // Creates and initializes a new runtime. EXPORT static bool Create(RuntimeArgumentMap&& runtime_options) SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_); // Creates and initializes a new runtime. EXPORT static bool Create(const RuntimeOptions& raw_options, bool ignore_unrecognized) SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_); enum class RuntimeDebugState { // This doesn't support any debug features / method tracing. This is the expected state usually. kNonJavaDebuggable, // This supports method tracing and a restricted set of debug features (for ex: redefinition // isn't supported). We transition to this state when method tracing has started or when the // debugger was attached and transition back to NonDebuggable once the tracing has stopped / // the debugger agent has detached.. kJavaDebuggable, // The runtime was started as a debuggable runtime. This allows us to support the extended set // of debug features (for ex: redefinition). We never transition out of this state. kJavaDebuggableAtInit }; bool EnsurePluginLoaded(const char* plugin_name, std::string* error_msg); bool EnsurePerfettoPlugin(std::string* error_msg); // IsAotCompiler for compilers that don't have a running runtime. Only dex2oat currently. bool IsAotCompiler() const { return !UseJitCompilation() && IsCompiler(); } // IsCompiler is any runtime which has a running compiler, either dex2oat or JIT. bool IsCompiler() const { return compiler_callbacks_ != nullptr; } // If a compiler, are we compiling a boot image? bool IsCompilingBootImage() const; bool CanRelocate() const; bool ShouldRelocate() const { return must_relocate_ && CanRelocate(); } bool MustRelocateIfPossible() const { return must_relocate_; } bool IsImageDex2OatEnabled() const { return image_dex2oat_enabled_; } CompilerCallbacks* GetCompilerCallbacks() { return compiler_callbacks_; } void SetCompilerCallbacks(CompilerCallbacks* callbacks) { CHECK(callbacks != nullptr); compiler_callbacks_ = callbacks; } bool IsZygote() const { return is_zygote_; } bool IsPrimaryZygote() const { return is_primary_zygote_; } bool IsSystemServer() const { return is_system_server_; } void SetAsSystemServer() { is_system_server_ = true; is_zygote_ = false; is_primary_zygote_ = false; } void SetAsZygoteChild(bool is_system_server, bool is_zygote) { // System server should have been set earlier in SetAsSystemServer. CHECK_EQ(is_system_server_, is_system_server); is_zygote_ = is_zygote; is_primary_zygote_ = false; } bool IsExplicitGcDisabled() const { return is_explicit_gc_disabled_; } bool IsEagerlyReleaseExplicitGcDisabled() const { return is_eagerly_release_explicit_gc_disabled_; } std::string GetCompilerExecutable() const; const std::vector& GetCompilerOptions() const { return compiler_options_; } void AddCompilerOption(const std::string& option) { compiler_options_.push_back(option); } const std::vector& GetImageCompilerOptions() const { return image_compiler_options_; } const std::vector& GetImageLocations() const { return image_locations_; } // Starts a runtime, which may cause threads to be started and code to run. bool Start() UNLOCK_FUNCTION(Locks::mutator_lock_); EXPORT bool IsShuttingDown(Thread* self); bool IsShuttingDownLocked() const REQUIRES(Locks::runtime_shutdown_lock_) { return shutting_down_.load(std::memory_order_relaxed); } bool IsShuttingDownUnsafe() const { return shutting_down_.load(std::memory_order_relaxed); } void SetShuttingDown() REQUIRES(Locks::runtime_shutdown_lock_) { shutting_down_.store(true, std::memory_order_relaxed); } size_t NumberOfThreadsBeingBorn() const REQUIRES(Locks::runtime_shutdown_lock_) { return threads_being_born_; } void StartThreadBirth() REQUIRES(Locks::runtime_shutdown_lock_) { threads_being_born_++; } EXPORT void EndThreadBirth() REQUIRES(Locks::runtime_shutdown_lock_); bool IsStarted() const { return started_; } bool IsFinishedStarting() const { return finished_starting_; } EXPORT void RunRootClinits(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); static Runtime* Current() { return instance_; } // Set the current runtime to be the given instance. // Note that this function is not responsible for cleaning up the old instance or taking the // ownership of the new instance. // // For test use only. static void TestOnlySetCurrent(Runtime* instance) { instance_ = instance; } // Set whichever abort message locations are appropriate to copies of the argument. Used by // Abort() and Thread::AbortInThis(). static void SetAbortMessage(const char* msg) REQUIRES(!Locks::abort_lock_); // Aborts semi-cleanly. Used in the implementation of LOG(FATAL), which most // callers should prefer. NO_RETURN EXPORT static void Abort(const char* msg) REQUIRES(!Locks::abort_lock_); // Returns the "main" ThreadGroup, used when attaching user threads. jobject GetMainThreadGroup() const; // Returns the "system" ThreadGroup, used when attaching our internal threads. EXPORT jobject GetSystemThreadGroup() const; // Returns the system ClassLoader which represents the CLASSPATH. EXPORT jobject GetSystemClassLoader() const; // Attaches the calling native thread to the runtime. EXPORT bool AttachCurrentThread(const char* thread_name, bool as_daemon, jobject thread_group, bool create_peer, bool should_run_callbacks = true); EXPORT void CallExitHook(jint status); // Detaches the current native thread from the runtime. void DetachCurrentThread(bool should_run_callbacks = true) REQUIRES(!Locks::mutator_lock_); // If we are handling SIQQUIT return the time when we received it. std::optional SiqQuitNanoTime() const; void DumpDeoptimizations(std::ostream& os); void DumpForSigQuit(std::ostream& os); void DumpLockHolders(std::ostream& os); EXPORT ~Runtime(); const std::vector& GetBootClassPath() const { return boot_class_path_; } const std::vector& GetBootClassPathLocations() const { DCHECK(boot_class_path_locations_.empty() || boot_class_path_locations_.size() == boot_class_path_.size()); return boot_class_path_locations_.empty() ? boot_class_path_ : boot_class_path_locations_; } // Dynamically adds an element to boot class path. EXPORT void AppendToBootClassPath( const std::string& filename, const std::string& location, const std::vector>& dex_files); // Same as above, but takes raw pointers. EXPORT void AppendToBootClassPath(const std::string& filename, const std::string& location, const std::vector& dex_files); // Same as above, but also takes a dex cache for each dex file. EXPORT void AppendToBootClassPath( const std::string& filename, const std::string& location, const std::vector>>& dex_files_and_cache); // Dynamically adds an element to boot class path and takes ownership of the dex files. EXPORT void AddExtraBootDexFiles(const std::string& filename, const std::string& location, std::vector>&& dex_files); ArrayRef GetBootClassPathFiles() { return ArrayRef(boot_class_path_files_); } ArrayRef GetBootClassPathImageFiles() { return ArrayRef(boot_class_path_image_files_); } ArrayRef GetBootClassPathVdexFiles() { return ArrayRef(boot_class_path_vdex_files_); } ArrayRef GetBootClassPathOatFiles() { return ArrayRef(boot_class_path_oat_files_); } // Returns the checksums for the boot image, extensions and extra boot class path dex files, // based on the image spaces and boot class path dex files loaded in memory. const std::string& GetBootClassPathChecksums() const { return boot_class_path_checksums_; } const std::string& GetClassPathString() const { return class_path_string_; } ClassLinker* GetClassLinker() const { return class_linker_; } jni::SmallLrtAllocator* GetSmallLrtAllocator() const { return small_lrt_allocator_; } jni::JniIdManager* GetJniIdManager() const { return jni_id_manager_.get(); } size_t GetDefaultStackSize() const { return default_stack_size_; } unsigned int GetFinalizerTimeoutMs() const { return finalizer_timeout_ms_; } gc::Heap* GetHeap() const { return heap_; } InternTable* GetInternTable() const { DCHECK(intern_table_ != nullptr); return intern_table_; } JavaVMExt* GetJavaVM() const { return java_vm_.get(); } size_t GetMaxSpinsBeforeThinLockInflation() const { return max_spins_before_thin_lock_inflation_; } MonitorList* GetMonitorList() const { return monitor_list_; } MonitorPool* GetMonitorPool() const { return monitor_pool_; } // Is the given object the special object used to mark a cleared JNI weak global? bool IsClearedJniWeakGlobal(ObjPtr obj) REQUIRES_SHARED(Locks::mutator_lock_); // Get the special object used to mark a cleared JNI weak global. mirror::Object* GetClearedJniWeakGlobal() REQUIRES_SHARED(Locks::mutator_lock_); EXPORT mirror::Throwable* GetPreAllocatedOutOfMemoryErrorWhenThrowingException() REQUIRES_SHARED(Locks::mutator_lock_); EXPORT mirror::Throwable* GetPreAllocatedOutOfMemoryErrorWhenThrowingOOME() REQUIRES_SHARED(Locks::mutator_lock_); EXPORT mirror::Throwable* GetPreAllocatedOutOfMemoryErrorWhenHandlingStackOverflow() REQUIRES_SHARED(Locks::mutator_lock_); EXPORT mirror::Throwable* GetPreAllocatedNoClassDefFoundError() REQUIRES_SHARED(Locks::mutator_lock_); const std::vector& GetProperties() const { return properties_; } ThreadList* GetThreadList() const { return thread_list_; } static const char* GetVersion() { return "2.1.0"; } bool IsMethodHandlesEnabled() const { return true; } void DisallowNewSystemWeaks() REQUIRES_SHARED(Locks::mutator_lock_); void AllowNewSystemWeaks() REQUIRES_SHARED(Locks::mutator_lock_); // broadcast_for_checkpoint is true when we broadcast for making blocking threads to respond to // checkpoint requests. It's false when we broadcast to unblock blocking threads after system weak // access is reenabled. void BroadcastForNewSystemWeaks(bool broadcast_for_checkpoint = false); // Visit all the roots. If only_dirty is true then non-dirty roots won't be visited. If // clean_dirty is true then dirty roots will be marked as non-dirty after visiting. EXPORT void VisitRoots(RootVisitor* visitor, VisitRootFlags flags = kVisitRootFlagAllRoots) REQUIRES(!Locks::classlinker_classes_lock_, !Locks::trace_lock_) REQUIRES_SHARED(Locks::mutator_lock_); // Visit image roots, only used for hprof since the GC uses the image space mod union table // instead. EXPORT void VisitImageRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); // Visit all of the roots we can safely visit concurrently. void VisitConcurrentRoots(RootVisitor* visitor, VisitRootFlags flags = kVisitRootFlagAllRoots) REQUIRES(!Locks::classlinker_classes_lock_, !Locks::trace_lock_) REQUIRES_SHARED(Locks::mutator_lock_); // Visit all of the non thread roots, we can do this with mutators unpaused. void VisitNonThreadRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); // Sweep system weaks, the system weak is deleted if the visitor return null. Otherwise, the // system weak is updated to be the visitor's returned value. EXPORT void SweepSystemWeaks(IsMarkedVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); // Walk all reflective objects and visit their targets as well as any method/fields held by the // runtime threads that are marked as being reflective. EXPORT void VisitReflectiveTargets(ReflectiveValueVisitor* visitor) REQUIRES(Locks::mutator_lock_); // Helper for visiting reflective targets with lambdas for both field and method reflective // targets. template void VisitReflectiveTargets(FieldVis&& fv, MethodVis&& mv) REQUIRES(Locks::mutator_lock_) { FunctionReflectiveValueVisitor frvv(fv, mv); VisitReflectiveTargets(&frvv); } // Returns a special method that calls into a trampoline for runtime method resolution ArtMethod* GetResolutionMethod(); bool HasResolutionMethod() const { return resolution_method_ != nullptr; } void SetResolutionMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_); void ClearResolutionMethod() { resolution_method_ = nullptr; } ArtMethod* CreateResolutionMethod() REQUIRES_SHARED(Locks::mutator_lock_); // Returns a special method that calls into a trampoline for runtime imt conflicts. ArtMethod* GetImtConflictMethod(); ArtMethod* GetImtUnimplementedMethod(); bool HasImtConflictMethod() const { return imt_conflict_method_ != nullptr; } void ClearImtConflictMethod() { imt_conflict_method_ = nullptr; } void FixupConflictTables() REQUIRES_SHARED(Locks::mutator_lock_); void SetImtConflictMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_); void SetImtUnimplementedMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_); ArtMethod* CreateImtConflictMethod(LinearAlloc* linear_alloc) REQUIRES_SHARED(Locks::mutator_lock_); void ClearImtUnimplementedMethod() { imt_unimplemented_method_ = nullptr; } bool HasCalleeSaveMethod(CalleeSaveType type) const { return callee_save_methods_[static_cast(type)] != 0u; } ArtMethod* GetCalleeSaveMethod(CalleeSaveType type) REQUIRES_SHARED(Locks::mutator_lock_); ArtMethod* GetCalleeSaveMethodUnchecked(CalleeSaveType type) REQUIRES_SHARED(Locks::mutator_lock_); QuickMethodFrameInfo GetRuntimeMethodFrameInfo(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_); static constexpr size_t GetCalleeSaveMethodOffset(CalleeSaveType type) { return OFFSETOF_MEMBER(Runtime, callee_save_methods_[static_cast(type)]); } static constexpr MemberOffset GetInstrumentationOffset() { return MemberOffset(OFFSETOF_MEMBER(Runtime, instrumentation_)); } InstructionSet GetInstructionSet() const { return instruction_set_; } EXPORT void SetInstructionSet(InstructionSet instruction_set); void ClearInstructionSet(); EXPORT void SetCalleeSaveMethod(ArtMethod* method, CalleeSaveType type); void ClearCalleeSaveMethods(); EXPORT ArtMethod* CreateCalleeSaveMethod() REQUIRES_SHARED(Locks::mutator_lock_); uint64_t GetStat(int kind); RuntimeStats* GetStats() { return &stats_; } bool HasStatsEnabled() const { return stats_enabled_; } void ResetStats(int kinds); void SetStatsEnabled(bool new_state) REQUIRES(!Locks::instrument_entrypoints_lock_, !Locks::mutator_lock_); enum class NativeBridgeAction { // private kUnload, kInitialize }; jit::Jit* GetJit() const { return jit_.get(); } jit::JitCodeCache* GetJitCodeCache() const { return jit_code_cache_.get(); } // Returns true if JIT compilations are enabled. GetJit() will be not null in this case. EXPORT bool UseJitCompilation() const; void PreZygoteFork(); void PostZygoteFork(); void InitNonZygoteOrPostFork( JNIEnv* env, bool is_system_server, bool is_child_zygote, NativeBridgeAction action, const char* isa, bool profile_system_server = false); const instrumentation::Instrumentation* GetInstrumentation() const { return &instrumentation_; } instrumentation::Instrumentation* GetInstrumentation() { return &instrumentation_; } void RegisterAppInfo(const std::string& package_name, const std::vector& code_paths, const std::string& profile_output_filename, const std::string& ref_profile_filename, int32_t code_type); void SetActiveTransaction() { DCHECK(IsAotCompiler()); active_transaction_ = true; } void ClearActiveTransaction() { DCHECK(IsAotCompiler()); active_transaction_ = false; } bool IsActiveTransaction() { return active_transaction_; } void SetFaultMessage(const std::string& message); void AddCurrentRuntimeFeaturesAsDex2OatArguments(std::vector* arg_vector) const; bool GetImplicitStackOverflowChecks() const { return implicit_so_checks_; } bool GetImplicitSuspendChecks() const { return implicit_suspend_checks_; } bool GetImplicitNullChecks() const { return implicit_null_checks_; } void DisableVerifier(); bool IsVerificationEnabled() const; EXPORT bool IsVerificationSoftFail() const; void SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy policy) { hidden_api_policy_ = policy; } hiddenapi::EnforcementPolicy GetHiddenApiEnforcementPolicy() const { return hidden_api_policy_; } void SetCorePlatformApiEnforcementPolicy(hiddenapi::EnforcementPolicy policy) { core_platform_api_policy_ = policy; } hiddenapi::EnforcementPolicy GetCorePlatformApiEnforcementPolicy() const { return core_platform_api_policy_; } void SetTestApiEnforcementPolicy(hiddenapi::EnforcementPolicy policy) { test_api_policy_ = policy; } hiddenapi::EnforcementPolicy GetTestApiEnforcementPolicy() const { return test_api_policy_; } void SetHiddenApiExemptions(const std::vector& exemptions) { hidden_api_exemptions_ = exemptions; } const std::vector& GetHiddenApiExemptions() { return hidden_api_exemptions_; } void SetDedupeHiddenApiWarnings(bool value) { dedupe_hidden_api_warnings_ = value; } bool ShouldDedupeHiddenApiWarnings() { return dedupe_hidden_api_warnings_; } void SetHiddenApiEventLogSampleRate(uint32_t rate) { hidden_api_access_event_log_rate_ = rate; } uint32_t GetHiddenApiEventLogSampleRate() const { return hidden_api_access_event_log_rate_; } const std::string& GetProcessPackageName() const { return process_package_name_; } void SetProcessPackageName(const char* package_name) { if (package_name == nullptr) { process_package_name_.clear(); } else { process_package_name_ = package_name; } } const std::string& GetProcessDataDirectory() const { return process_data_directory_; } void SetProcessDataDirectory(const char* data_dir) { if (data_dir == nullptr) { process_data_directory_.clear(); } else { process_data_directory_ = data_dir; } } const std::vector& GetCpuAbilist() const { return cpu_abilist_; } bool IsRunningOnMemoryTool() const { return is_running_on_memory_tool_; } void SetTargetSdkVersion(uint32_t version) { target_sdk_version_ = version; } uint32_t GetTargetSdkVersion() const { return target_sdk_version_; } CompatFramework& GetCompatFramework() { return compat_framework_; } uint32_t GetZygoteMaxFailedBoots() const { return zygote_max_failed_boots_; } bool AreExperimentalFlagsEnabled(ExperimentalFlags flags) { return (experimental_flags_ & flags) != ExperimentalFlags::kNone; } void CreateJitCodeCache(bool rwx_memory_allowed); // Create the JIT and instrumentation and code cache. void CreateJit(); ArenaPool* GetLinearAllocArenaPool() { return linear_alloc_arena_pool_.get(); } ArenaPool* GetArenaPool() { return arena_pool_.get(); } const ArenaPool* GetArenaPool() const { return arena_pool_.get(); } ArenaPool* GetJitArenaPool() { return jit_arena_pool_.get(); } EXPORT void ReclaimArenaPoolMemory(); LinearAlloc* GetLinearAlloc() { return linear_alloc_.get(); } LinearAlloc* GetStartupLinearAlloc() { return startup_linear_alloc_.load(std::memory_order_relaxed); } jit::JitOptions* GetJITOptions() { return jit_options_.get(); } bool IsJavaDebuggable() const { return runtime_debug_state_ == RuntimeDebugState::kJavaDebuggable || runtime_debug_state_ == RuntimeDebugState::kJavaDebuggableAtInit; } bool IsJavaDebuggableAtInit() const { return runtime_debug_state_ == RuntimeDebugState::kJavaDebuggableAtInit; } void SetProfileableFromShell(bool value) { is_profileable_from_shell_ = value; } bool IsProfileableFromShell() const { return is_profileable_from_shell_; } void SetProfileable(bool value) { is_profileable_ = value; } bool IsProfileable() const { return is_profileable_; } EXPORT void SetRuntimeDebugState(RuntimeDebugState state); // Deoptimize the boot image, called for Java debuggable apps. EXPORT void DeoptimizeBootImage() REQUIRES(Locks::mutator_lock_); bool IsNativeDebuggable() const { return is_native_debuggable_; } void SetNativeDebuggable(bool value) { is_native_debuggable_ = value; } void SetSignalHookDebuggable(bool value); bool AreNonStandardExitsEnabled() const { return non_standard_exits_enabled_; } void SetNonStandardExitsEnabled() { non_standard_exits_enabled_ = true; } bool AreAsyncExceptionsThrown() const { return async_exceptions_thrown_; } void SetAsyncExceptionsThrown() { async_exceptions_thrown_ = true; } // Returns the build fingerprint, if set. Otherwise an empty string is returned. std::string GetFingerprint() { return fingerprint_; } // Called from class linker. void SetSentinel(ObjPtr sentinel) REQUIRES_SHARED(Locks::mutator_lock_); // For testing purpose only. // TODO: Remove this when this is no longer needed (b/116087961). EXPORT GcRoot GetSentinel() REQUIRES_SHARED(Locks::mutator_lock_); // Use a sentinel for marking entries in a table that have been cleared. // This helps diagnosing in case code tries to wrongly access such // entries. static mirror::Class* GetWeakClassSentinel() { return reinterpret_cast(0xebadbeef); } // Create a normal LinearAlloc or low 4gb version if we are 64 bit AOT compiler. EXPORT LinearAlloc* CreateLinearAlloc(); // Setup linear-alloc allocators to stop using the current arena so that the // next allocations, which would be after zygote fork, happens in userfaultfd // visited space. void SetupLinearAllocForPostZygoteFork(Thread* self) REQUIRES(!Locks::mutator_lock_, !Locks::classlinker_classes_lock_); OatFileManager& GetOatFileManager() const { DCHECK(oat_file_manager_ != nullptr); return *oat_file_manager_; } double GetHashTableMinLoadFactor() const; double GetHashTableMaxLoadFactor() const; bool IsSafeMode() const { return safe_mode_; } void SetSafeMode(bool mode) { safe_mode_ = mode; } bool GetDumpNativeStackOnSigQuit() const { return dump_native_stack_on_sig_quit_; } EXPORT void UpdateProcessState(ProcessState process_state); // Returns true if we currently care about long mutator pause. bool InJankPerceptibleProcessState() const { return process_state_ == kProcessStateJankPerceptible; } void RegisterSensitiveThread() const; void SetZygoteNoThreadSection(bool val) { zygote_no_threads_ = val; } bool IsZygoteNoThreadSection() const { return zygote_no_threads_; } // Returns if the code can be deoptimized asynchronously. Code may be compiled with some // optimization that makes it impossible to deoptimize. EXPORT bool IsAsyncDeoptimizeable(ArtMethod* method, uintptr_t code) const REQUIRES_SHARED(Locks::mutator_lock_); // Returns a saved copy of the environment (getenv/setenv values). // Used by Fork to protect against overwriting LD_LIBRARY_PATH, etc. char** GetEnvSnapshot() const { return env_snapshot_.GetSnapshot(); } EXPORT void AddSystemWeakHolder(gc::AbstractSystemWeakHolder* holder); EXPORT void RemoveSystemWeakHolder(gc::AbstractSystemWeakHolder* holder); EXPORT void AttachAgent(JNIEnv* env, const std::string& agent_arg, jobject class_loader); const std::list>& GetAgents() const { return agents_; } EXPORT RuntimeCallbacks* GetRuntimeCallbacks(); bool HasLoadedPlugins() const { return !plugins_.empty(); } void InitThreadGroups(Thread* self); void SetDumpGCPerformanceOnShutdown(bool value) { dump_gc_performance_on_shutdown_ = value; } bool GetDumpGCPerformanceOnShutdown() const { return dump_gc_performance_on_shutdown_; } void IncrementDeoptimizationCount(DeoptimizationKind kind) { DCHECK_LE(kind, DeoptimizationKind::kLast); deoptimization_counts_[static_cast(kind)]++; } uint32_t GetNumberOfDeoptimizations() const { uint32_t result = 0; for (size_t i = 0; i <= static_cast(DeoptimizationKind::kLast); ++i) { result += deoptimization_counts_[i]; } return result; } bool DenyArtApexDataFiles() const { return deny_art_apex_data_files_; } size_t GetMadviseWillNeedTotalDexSize() const { return madvise_willneed_total_dex_size_; } size_t GetMadviseWillNeedSizeOdex() const { return madvise_willneed_odex_filesize_; } size_t GetMadviseWillNeedSizeArt() const { return madvise_willneed_art_filesize_; } const std::string& GetJdwpOptions() { return jdwp_options_; } JdwpProvider GetJdwpProvider() const { return jdwp_provider_; } JniIdType GetJniIdType() const { return jni_ids_indirection_; } bool CanSetJniIdType() const { return GetJniIdType() == JniIdType::kSwapablePointer; } // Changes the JniIdType to the given type. Only allowed if CanSetJniIdType(). All threads must be // suspended to call this function. EXPORT void SetJniIdType(JniIdType t); uint32_t GetVerifierLoggingThresholdMs() const { return verifier_logging_threshold_ms_; } // Atomically delete the thread pool if the reference count is 0. bool DeleteThreadPool() REQUIRES(!Locks::runtime_thread_pool_lock_); // Wait for all the thread workers to be attached. void WaitForThreadPoolWorkersToStart() REQUIRES(!Locks::runtime_thread_pool_lock_); // Scoped usage of the runtime thread pool. Prevents the pool from being // deleted. Note that the thread pool is only for startup and gets deleted after. class ScopedThreadPoolUsage { public: ScopedThreadPoolUsage(); ~ScopedThreadPoolUsage(); // Return the thread pool. ThreadPool* GetThreadPool() const { return thread_pool_; } private: ThreadPool* const thread_pool_; }; LinearAlloc* ReleaseStartupLinearAlloc() { return startup_linear_alloc_.exchange(nullptr, std::memory_order_relaxed); } bool LoadAppImageStartupCache() const { return load_app_image_startup_cache_; } void SetLoadAppImageStartupCacheEnabled(bool enabled) { load_app_image_startup_cache_ = enabled; } // Reset the startup completed status so that we can call NotifyStartupCompleted again. Should // only be used for testing. EXPORT void ResetStartupCompleted(); // Notify the runtime that application startup is considered completed. Only has effect for the // first call. Returns whether this was the first call. bool NotifyStartupCompleted(); // Notify the runtime that the application finished loading some dex/odex files. This is // called everytime we load a set of dex files in a class loader. void NotifyDexFileLoaded(); // Return true if startup is already completed. EXPORT bool GetStartupCompleted() const; bool IsVerifierMissingKThrowFatal() const { return verifier_missing_kthrow_fatal_; } bool IsJavaZygoteForkLoopRequired() const { return force_java_zygote_fork_loop_; } bool IsPerfettoHprofEnabled() const { return perfetto_hprof_enabled_; } bool IsPerfettoJavaHeapStackProfEnabled() const { return perfetto_javaheapprof_enabled_; } bool IsMonitorTimeoutEnabled() const { return monitor_timeout_enable_; } uint64_t GetMonitorTimeoutNs() const { return monitor_timeout_ns_; } // Return whether this is system server and it is being profiled. bool IsSystemServerProfiled() const; // Return whether we should load oat files as executable or not. bool GetOatFilesExecutable() const; metrics::ArtMetrics* GetMetrics() { return &metrics_; } AppInfo* GetAppInfo() { return &app_info_; } void RequestMetricsReport(bool synchronous = true); static void MadviseFileForRange(size_t madvise_size_limit_bytes, size_t map_size_bytes, const uint8_t* map_begin, const uint8_t* map_end, const std::string& file_name); const std::string& GetApexVersions() const { return apex_versions_; } // Return whether a boot image has a profile. This means it's an in-memory // image rather that an image loaded from disk. bool HasImageWithProfile() const; bool GetNoSigChain() const { return no_sig_chain_; } void AddGeneratedCodeRange(const void* start, size_t size); void RemoveGeneratedCodeRange(const void* start, size_t size) REQUIRES_SHARED(Locks::mutator_lock_); // Trigger a flag reload from system properties or device congfigs. // // Should only be called from runtime init and zygote post fork as // we don't want to change the runtime config midway during execution. // // The caller argument should be the name of the function making this call // and will be used to enforce the appropriate names. // // See Flags::ReloadAllFlags as well. static void ReloadAllFlags(const std::string& caller); // Parses /apex/apex-info-list.xml to build a string containing apex versions of boot classpath // jars, which is encoded into .oat files. static std::string GetApexVersions(ArrayRef boot_class_path_locations); bool AllowInMemoryCompilation() const { return allow_in_memory_compilation_; } // Used by plugin code to attach a hook for OOME. void SetOutOfMemoryErrorHook(void (*hook)()) { out_of_memory_error_hook_ = hook; } void OutOfMemoryErrorHook() { if (out_of_memory_error_hook_ != nullptr) { out_of_memory_error_hook_(); } } private: static void InitPlatformSignalHandlers(); Runtime(); bool HandlesSignalsInCompiledCode() const { return !no_sig_chain_ && (implicit_null_checks_ || implicit_so_checks_ || implicit_suspend_checks_); } void BlockSignals(); bool Init(RuntimeArgumentMap&& runtime_options) SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_); void InitNativeMethods() REQUIRES(!Locks::mutator_lock_); void RegisterRuntimeNativeMethods(JNIEnv* env); void InitMetrics(); void StartDaemonThreads() REQUIRES_SHARED(Locks::mutator_lock_); void StartSignalCatcher(); void MaybeSaveJitProfilingInfo(); // Visit all of the thread roots. void VisitThreadRoots(RootVisitor* visitor, VisitRootFlags flags) REQUIRES_SHARED(Locks::mutator_lock_); // Visit all other roots which must be done with mutators suspended. void VisitNonConcurrentRoots(RootVisitor* visitor, VisitRootFlags flags) REQUIRES_SHARED(Locks::mutator_lock_); // Constant roots are the roots which never change after the runtime is initialized, they only // need to be visited once per GC cycle. void VisitConstantRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); // Note: To be lock-free, GetFaultMessage temporarily replaces the lock message with null. // As such, there is a window where a call will return an empty string. In general, // only aborting code should retrieve this data (via GetFaultMessageForAbortLogging // friend). std::string GetFaultMessage(); ThreadPool* AcquireThreadPool() REQUIRES(!Locks::runtime_thread_pool_lock_); void ReleaseThreadPool() REQUIRES(!Locks::runtime_thread_pool_lock_); // Caches the apex versions produced by `GetApexVersions`. void InitializeApexVersions(); void AppendToBootClassPath(const std::string& filename, const std::string& location); // Don't use EXPORT ("default" visibility), because quick_entrypoints_x86.o // refers to this symbol and it can't link with R_386_PC32 relocation. // A pointer to the active runtime or null. LIBART_PROTECTED static Runtime* instance_; // NOTE: these must match the gc::ProcessState values as they come directly from the framework. static constexpr int kProfileForground = 0; static constexpr int kProfileBackground = 1; static constexpr uint32_t kCalleeSaveSize = 6u; // 64 bit so that we can share the same asm offsets for both 32 and 64 bits. uint64_t callee_save_methods_[kCalleeSaveSize]; // Pre-allocated exceptions (see Runtime::Init). GcRoot pre_allocated_OutOfMemoryError_when_throwing_exception_; GcRoot pre_allocated_OutOfMemoryError_when_throwing_oome_; GcRoot pre_allocated_OutOfMemoryError_when_handling_stack_overflow_; GcRoot pre_allocated_NoClassDefFoundError_; ArtMethod* resolution_method_; ArtMethod* imt_conflict_method_; // Unresolved method has the same behavior as the conflict method, it is used by the class linker // for differentiating between unfilled imt slots vs conflict slots in superclasses. ArtMethod* imt_unimplemented_method_; // Special sentinel object used to invalid conditions in JNI (cleared weak references) and // JDWP (invalid references). GcRoot sentinel_; InstructionSet instruction_set_; CompilerCallbacks* compiler_callbacks_; bool is_zygote_; bool is_primary_zygote_; bool is_system_server_; bool must_relocate_; bool is_concurrent_gc_enabled_; bool is_explicit_gc_disabled_; bool is_eagerly_release_explicit_gc_disabled_; bool image_dex2oat_enabled_; std::string compiler_executable_; std::vector compiler_options_; std::vector image_compiler_options_; std::vector image_locations_; std::vector boot_class_path_; std::vector boot_class_path_locations_; std::string boot_class_path_checksums_; std::vector boot_class_path_files_; std::vector boot_class_path_image_files_; std::vector boot_class_path_vdex_files_; std::vector boot_class_path_oat_files_; std::string class_path_string_; std::vector properties_; std::list agent_specs_; std::list> agents_; std::vector plugins_; // The default stack size for managed threads created by the runtime. size_t default_stack_size_; // Finalizers running for longer than this many milliseconds abort the runtime. unsigned int finalizer_timeout_ms_; gc::Heap* heap_; std::unique_ptr jit_arena_pool_; std::unique_ptr arena_pool_; // This pool is used for linear alloc if we are using userfaultfd GC, or if // low 4gb pool is required for compiler linear alloc. Otherwise, use // arena_pool_. // We need ArtFields to be in low 4gb if we are compiling using a 32 bit image // on a 64 bit compiler in case we resolve things in the image since the field // arrays are int arrays in this case. std::unique_ptr linear_alloc_arena_pool_; // Shared linear alloc for now. std::unique_ptr linear_alloc_; // Linear alloc used for allocations during startup. Will be deleted after // startup. Atomic because the pointer can be concurrently updated to null. std::atomic startup_linear_alloc_; // The number of spins that are done before thread suspension is used to forcibly inflate. size_t max_spins_before_thin_lock_inflation_; MonitorList* monitor_list_; MonitorPool* monitor_pool_; ThreadList* thread_list_; InternTable* intern_table_; ClassLinker* class_linker_; SignalCatcher* signal_catcher_; jni::SmallLrtAllocator* small_lrt_allocator_; std::unique_ptr jni_id_manager_; std::unique_ptr java_vm_; std::unique_ptr jit_; std::unique_ptr jit_code_cache_; std::unique_ptr jit_options_; // Runtime thread pool. The pool is only for startup and gets deleted after. std::unique_ptr thread_pool_ GUARDED_BY(Locks::runtime_thread_pool_lock_); size_t thread_pool_ref_count_ GUARDED_BY(Locks::runtime_thread_pool_lock_); // Fault message, printed when we get a SIGSEGV. Stored as a native-heap object and accessed // lock-free, so needs to be atomic. std::atomic fault_message_; // A non-zero value indicates that a thread has been created but not yet initialized. Guarded by // the shutdown lock so that threads aren't born while we're shutting down. size_t threads_being_born_ GUARDED_BY(Locks::runtime_shutdown_lock_); // Waited upon until no threads are being born. std::unique_ptr shutdown_cond_ GUARDED_BY(Locks::runtime_shutdown_lock_); // Set when runtime shutdown is past the point that new threads may attach. Usually // GUARDED_BY(Locks::runtime_shutdown_lock_). But we need to check it in Abort without the // lock, because we may already own it. std::atomic shutting_down_; // The runtime is starting to shutdown but is blocked waiting on shutdown_cond_. bool shutting_down_started_ GUARDED_BY(Locks::runtime_shutdown_lock_); bool started_; // New flag added which tells us if the runtime has finished starting. If // this flag is set then the Daemon threads are created and the class loader // is created. This flag is needed for knowing if its safe to request CMS. bool finished_starting_; // Hooks supported by JNI_CreateJavaVM jint (*vfprintf_)(FILE* stream, const char* format, va_list ap); void (*exit_)(jint status); void (*abort_)(); bool stats_enabled_; RuntimeStats stats_; const bool is_running_on_memory_tool_; std::unique_ptr trace_config_; instrumentation::Instrumentation instrumentation_; jobject main_thread_group_; jobject system_thread_group_; // As returned by ClassLoader.getSystemClassLoader(). jobject system_class_loader_; // If true, then we dump the GC cumulative timings on shutdown. bool dump_gc_performance_on_shutdown_; // Transactions are handled by the `AotClassLinker` but we keep a simple flag // in the `Runtime` for quick transaction checks. // Code that's not AOT-specific but needs some transaction-specific behavior // shall check this flag and, for an active transaction, make virtual calls // through `ClassLinker` to `AotClassLinker` to implement that behavior. bool active_transaction_; // If kNone, verification is disabled. kEnable by default. verifier::VerifyMode verify_; // List of supported cpu abis. std::vector cpu_abilist_; // Specifies target SDK version to allow workarounds for certain API levels. uint32_t target_sdk_version_; // ART counterpart for the compat framework (go/compat-framework). CompatFramework compat_framework_; // Implicit checks flags. bool implicit_null_checks_; // NullPointer checks are implicit. bool implicit_so_checks_; // StackOverflow checks are implicit. bool implicit_suspend_checks_; // Thread suspension checks are implicit. // Whether or not the sig chain (and implicitly the fault handler) should be // disabled. Tools like dex2oat don't need them. This enables // building a statically link version of dex2oat. bool no_sig_chain_; // Force the use of native bridge even if the app ISA matches the runtime ISA. bool force_native_bridge_; // Whether or not a native bridge has been loaded. // // The native bridge allows running native code compiled for a foreign ISA. The way it works is, // if standard dlopen fails to load native library associated with native activity, it calls to // the native bridge to load it and then gets the trampoline for the entry to native activity. // // The option 'native_bridge_library_filename' specifies the name of the native bridge. // When non-empty the native bridge will be loaded from the given file. An empty value means // that there's no native bridge. bool is_native_bridge_loaded_; // Whether we are running under native debugger. bool is_native_debuggable_; // whether or not any async exceptions have ever been thrown. This is used to speed up the // MterpShouldSwitchInterpreters function. bool async_exceptions_thrown_; // Whether anything is going to be using the shadow-frame APIs to force a function to return // early. Doing this requires that (1) we be debuggable and (2) that mterp is exited. bool non_standard_exits_enabled_; // Whether Java code needs to be debuggable. RuntimeDebugState runtime_debug_state_; bool monitor_timeout_enable_; uint64_t monitor_timeout_ns_; // Whether or not this application can be profiled by the shell user, // even when running on a device that is running in user mode. bool is_profileable_from_shell_ = false; // Whether or not this application can be profiled by system services on a // device running in user mode, but not necessarily by the shell user. bool is_profileable_ = false; // The maximum number of failed boots we allow before pruning the dalvik cache // and trying again. This option is only inspected when we're running as a // zygote. uint32_t zygote_max_failed_boots_; // Enable experimental opcodes that aren't fully specified yet. The intent is to // eventually publish them as public-usable opcodes, but they aren't ready yet. // // Experimental opcodes should not be used by other production code. ExperimentalFlags experimental_flags_; // Contains the build fingerprint, if given as a parameter. std::string fingerprint_; // Oat file manager, keeps track of what oat files are open. OatFileManager* oat_file_manager_; // Whether or not we are on a low RAM device. bool is_low_memory_mode_; // Limiting size (in bytes) for applying MADV_WILLNEED on vdex files // or uncompressed dex files in APKs. // A 0 for this will turn off madvising to MADV_WILLNEED size_t madvise_willneed_total_dex_size_; // Limiting size (in bytes) for applying MADV_WILLNEED on odex files // A 0 for this will turn off madvising to MADV_WILLNEED size_t madvise_willneed_odex_filesize_; // Limiting size (in bytes) for applying MADV_WILLNEED on art files // A 0 for this will turn off madvising to MADV_WILLNEED size_t madvise_willneed_art_filesize_; // Whether the application should run in safe mode, that is, interpreter only. bool safe_mode_; // Whether access checks on hidden API should be performed. hiddenapi::EnforcementPolicy hidden_api_policy_; // Whether access checks on core platform API should be performed. hiddenapi::EnforcementPolicy core_platform_api_policy_; // Whether access checks on test API should be performed. hiddenapi::EnforcementPolicy test_api_policy_; // List of signature prefixes of methods that have been removed from the blocklist, and treated // as if SDK. std::vector hidden_api_exemptions_; // Do not warn about the same hidden API access violation twice. // This is only used for testing. bool dedupe_hidden_api_warnings_; // How often to log hidden API access to the event log. An integer between 0 // (never) and 0x10000 (always). uint32_t hidden_api_access_event_log_rate_; // The package of the app running in this process. std::string process_package_name_; // The data directory of the app running in this process. std::string process_data_directory_; // Whether threads should dump their native stack on SIGQUIT. bool dump_native_stack_on_sig_quit_; // Whether or not we currently care about pause times. ProcessState process_state_; // Whether zygote code is in a section that should not start threads. bool zygote_no_threads_; // The string containing requested jdwp options std::string jdwp_options_; // The jdwp provider we were configured with. JdwpProvider jdwp_provider_; // True if jmethodID and jfieldID are opaque Indices. When false (the default) these are simply // pointers. This is set by -Xopaque-jni-ids:{true,false}. JniIdType jni_ids_indirection_; // Set to false in cases where we want to directly control when jni-id // indirection is changed. This is intended only for testing JNI id swapping. bool automatically_set_jni_ids_indirection_; // True if files in /data/misc/apexdata/com.android.art are considered untrustworthy. bool deny_art_apex_data_files_; // Whether to allow compiling the boot classpath in memory when the given boot image is unusable. bool allow_in_memory_compilation_ = false; // Saved environment. class EnvSnapshot { public: EnvSnapshot() = default; void TakeSnapshot(); char** GetSnapshot() const; private: std::unique_ptr c_env_vector_; std::vector> name_value_pairs_; DISALLOW_COPY_AND_ASSIGN(EnvSnapshot); } env_snapshot_; // Generic system-weak holders. std::vector system_weak_holders_; std::unique_ptr callbacks_; std::atomic deoptimization_counts_[ static_cast(DeoptimizationKind::kLast) + 1]; MemMap protected_fault_page_; uint32_t verifier_logging_threshold_ms_; bool load_app_image_startup_cache_ = false; // If startup has completed, must happen at most once. std::atomic startup_completed_ = false; bool verifier_missing_kthrow_fatal_; bool force_java_zygote_fork_loop_; bool perfetto_hprof_enabled_; bool perfetto_javaheapprof_enabled_; // Called on out of memory error void (*out_of_memory_error_hook_)(); metrics::ArtMetrics metrics_; std::unique_ptr metrics_reporter_; // Apex versions of boot classpath jars concatenated in a string. The format // is of the type: // '/apex1_version/apex2_version//' // // When the apex is the factory version, we don't encode it (for example in // the third entry in the example above). std::string apex_versions_; // The info about the application code paths. AppInfo app_info_; // Note: See comments on GetFaultMessage. friend std::string GetFaultMessageForAbortLogging(); friend class Dex2oatImageTest; friend class ScopedThreadPoolUsage; friend class OatFileAssistantTest; class SetupLinearAllocForZygoteFork; DISALLOW_COPY_AND_ASSIGN(Runtime); }; inline metrics::ArtMetrics* GetMetrics() { return Runtime::Current()->GetMetrics(); } } // namespace art #endif // ART_RUNTIME_RUNTIME_H_