Android ART虚拟机 对象创建内存分配流程
Posted baiiu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android ART虚拟机 对象创建内存分配流程相关的知识,希望对你有一定的参考价值。
前言
本篇文章介绍我们在日常开发使用Java时new对象的时,ART在堆上的内存分配是如何分配的。内存又和gc相关,下篇文章会分析ART的gc流程。本文可以参考之前写的Dalivk虚拟机下的对象创建时内存分配流程一起看,会对ART虚拟机理解的更深刻些。
解释执行下
NEW_INSTANCE、NEW_ARRAY指令执行流程如下。
art/runtime/interpreter/interpreter_switch_impl.cc#ExecuteSwitchImpl
template<bool do_access_check, bool transaction_active>
JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
ShadowFrame& shadow_frame, JValue result_register,
bool interpret_one_instruction)
constexpr bool do_assignability_check = do_access_check;
self->VerifyStack();
uint32_t dex_pc = shadow_frame.GetDexPC();
const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
const uint16_t* const insns = code_item->insns_;
const Instruction* inst = Instruction::At(insns + dex_pc);
uint16_t inst_data;
ArtMethod* method = shadow_frame.GetMethod();
jit::Jit* jit = Runtime::Current()->GetJit();
std::unique_ptr<lambda::ClosureBuilder> lambda_closure_builder;
size_t lambda_captured_variable_index = 0;
do
dex_pc = inst->GetDexPc(insns);
shadow_frame.SetDexPC(dex_pc);
TraceExecution(shadow_frame, inst, dex_pc);
inst_data = inst->Fetch16(0);
switch (inst->Opcode(inst_data))
case Instruction::NEW_INSTANCE:
PREAMBLE();
Object* obj = nullptr;
Class* c = ResolveVerifyAndClinit(inst->VRegB_21c(), shadow_frame.GetMethod(), self, false, do_access_check);
if (LIKELY(c != nullptr))
if (UNLIKELY(c->IsStringClass()))
// 是String的话
gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
mirror::SetStringCountVisitor visitor(0);
obj = String::Alloc<true>(self, 0, allocator_type, visitor);
else
// 非String调用AllocObjectFromCode分配内存
obj = AllocObjectFromCode<do_access_check, true>(inst->VRegB_21c(), shadow_frame.GetMethod(), self, Runtime::Current()->GetHeap()->GetCurrentAllocator());
...
inst = inst->Next_2xx();
break;
case Instruction::NEW_ARRAY:
int32_t length = shadow_frame.GetVReg(inst->VRegB_22c(inst_data));
// 调用AllocArrayFromCode进行分配
Object* obj = AllocArrayFromCode<do_access_check, true>(inst->VRegC_22c(), length, shadow_frame.GetMethod(), self, Runtime::Current()->GetHeap()->GetCurrentAllocator());
shadow_frame.SetVRegReference(inst->VRegA_22c(inst_data), obj);
inst = inst->Next_2xx();
break;
while (!interpret_one_instruction);
// Record where we stopped.
shadow_frame.SetDexPC(inst->GetDexPc(insns));
return result_register;
String::Alloc
最终调用AllocObjectWithAllocator
art/runtime/mirror/string.h
art/runtime/mirror/string.cc
art/runtime/mirror/string-inl.h
// C++ mirror of java.lang.String
class MANAGED String FINAL : public Object
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
int32_t count_;
uint32_t hash_code_;
// 真正存储字符串的地方
uint16_t value_[0];
template <bool kIsInstrumented, typename PreFenceVisitor>
inline String* String::Alloc(Thread* self, int32_t utf16_length, gc::AllocatorType allocator_type, const PreFenceVisitor& pre_fence_visitor)
constexpr size_t header_size = sizeof(String);
static_assert(sizeof(utf16_length) <= sizeof(size_t), "static_cast<size_t>(utf16_length) must not lose bits.");
size_t length = static_cast<size_t>(utf16_length);
size_t data_size = sizeof(uint16_t) * length; // 字符内容大小
size_t size = header_size + data_size; // 该字符串整个的大小
// String.equals() intrinsics assume zero-padding up to kObjectAlignment, so make sure the allocator clears the padding as well.
size_t alloc_size = RoundUp(size, kObjectAlignment);
Class* string_class = GetJavaLangString();
...
gc::Heap* heap = Runtime::Current()->GetHeap();
return down_cast<String*>(
heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, string_class, alloc_size,
allocator_type, pre_fence_visitor));
AllocObjectFromCode
最终调用AllocObjectWithAllocator
art/runtime/entrypoints/entrypoint_utils-inl.h
art/runtime/mirror/class-inl.h
// Given the context of a calling Method, use its DexCache to resolve a type to a Class.
// If it cannot be resolved, throw an error. If it can, use it to create an instance.
// When verification/compiler hasn't been able to verify access, optionally perform an access check.
template <bool kAccessCheck, bool kInstrumented>
ALWAYS_INLINE
inline mirror::Object* AllocObjectFromCode(uint32_t type_idx, ArtMethod* method, Thread* self, gc::AllocatorType allocator_type)
mirror::Class* klass = CheckObjectAlloc<kAccessCheck>(type_idx, method, self, &slow_path);
return klass->Alloc<kInstrumented>(self, allocator_type);
template<bool kIsInstrumented, bool kCheckAddFinalizer>
inline Object* Class::Alloc(Thread* self, gc::AllocatorType allocator_type)
CheckObjectAlloc();
gc::Heap* heap = Runtime::Current()->GetHeap();
mirror::Object* obj =
heap->AllocObjectWithAllocator<kIsInstrumented, false>(self, this, this->object_size_,
allocator_type, VoidFunctor());
return obj;
AllocArrayFromCode
最终调用AllocObjectWithAllocator
art/runtime/entrypoints/entrypoint_utils-inl.h
art/runtime/mirror/array.h
art/runtime/mirror/array-inl.h
// Given the context of a calling Method, use its DexCache to resolve a type to an array Class.
// If it cannot be resolved, throw an error. If it can, use it to create an array.
// When verification/compiler hasn't been able to verify access, optionally perform an access check.
template <bool kAccessCheck, bool kInstrumented>
ALWAYS_INLINE
inline mirror::Array* AllocArrayFromCode(uint32_t type_idx,
int32_t component_count,
ArtMethod* method,
Thread* self,
gc::AllocatorType allocator_type)
mirror::Class* klass = CheckArrayAlloc<kAccessCheck>(type_idx, component_count, method,
&slow_path);
return mirror::Array::Alloc<kInstrumented>(self, klass, component_count,
klass->GetComponentSizeShift(), allocator_type);
class MANAGED Array : public Object
// The number of array elements.
int32_t length_;
// Marker for the data (used by generated code)
uint32_t first_element_[0];
template <bool kIsInstrumented, bool kFillUsable>
inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count, size_t component_size_shift, gc::AllocatorType allocator_type)
// 计算数组最终需要的内存大小
size_t size = ComputeArraySize(component_count, component_size_shift);
gc::Heap* heap = Runtime::Current()->GetHeap();
Array* result;
if (!kFillUsable)
SetLengthVisitor visitor(component_count);
result = down_cast<Array*>(heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size, allocator_type, visitor));
else
SetLengthToUsableSizeVisitor visitor(component_count, DataOffset(1U << component_size_shift).SizeValue(), component_size_shift);
result = down_cast<Array*>(heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size, allocator_type, visitor));
return result;
机器码执行下
机器码执行下最终也调用到AllocObjectWithAllocator
流程略
AllocObjectWithAllocator
art/runtime/gc/heap-inl.h
// kInstrumented,和工具使用有关
// kCheckLargeObject,判断要分配的内存大小是否属于大对象范围
// PreFenceVisitor,函数对象,用于分配完成的回调
template <bool kInstrumented, bool kCheckLargeObject, typename PreFenceVisitor>
inline mirror::Object* Heap::AllocObjectWithAllocator(Thread* self,
mirror::Class* klass,
size_t byte_count,
AllocatorType allocator,
const PreFenceVisitor& pre_fence_visitor)
mirror::Object* obj;
if (kCheckLargeObject && UNLIKELY(ShouldAllocLargeObject(klass, byte_count)))
// AllocLargeObject以kAllocatorTypeLOS类型再次调用AllocObjectWithAllocator,且kCheckLargeObject为false
obj = AllocLargeObject<kInstrumented, PreFenceVisitor>(self, &klass, byte_count, pre_fence_visitor);
if (obj != nullptr)
return obj;
else
// There should be an OOM exception, since we are retrying, clear it.
self->ClearException();
// If the large object allocation failed, try to use the normal spaces (main space, non moving space).
// This can happen if there is significant virtual address space fragmentation.
// kAllocatorTypeLOS内存分配器分配失败了,就在其他类型的内存分配器上尝试下
// bytes allocated for the (individual) object.
size_t bytes_allocated;
size_t usable_size;
size_t new_num_bytes_allocated = 0;
if (allocator == kAllocatorTypeTLAB || allocator == kAllocatorTypeRegionTLAB)
byte_count = RoundUp(byte_count, space::BumpPointerSpace::kAlignment);
// If we have a thread local allocation we don't need to update bytes allocated.
// 如果是使用线程本地资源,如果TLAB足够分配就在TLAB内分配;
if ((allocator == kAllocatorTypeTLAB || allocator == kAllocatorTypeRegionTLAB) &&
byte_count <= self->TlabSize())
obj = self->AllocTlab(byte_count);
obj->SetClass(klass);
bytes_allocated = byte_count;
usable_size = bytes_allocated;
pre_fence_visitor(obj, usable_size); // 回调
QuasiAtomic::ThreadFenceForConstructor();
else if (!kInstrumented && allocator == kAllocatorTypeRosAlloc &&
(obj = rosalloc_space_->AllocThreadLocal(self, byte_count, &bytes_allocated)) &&
LIKELY(obj != nullptr))
// 如果使用kAllocatorTypeRosAlloc则在rosalloc_space_内分配
obj->SetClass(klass);
usable_size = bytes_allocated;
pre_fence_visitor(obj, usable_size);
QuasiAtomic::ThreadFenceForConstructor();
else
// bytes allocated that takes bulk thread-local buffer allocations into account.
// 前面都分配失败了(可能是内存分配器不足了),则调用TryToAllocate进行分配
size_t bytes_tl_bulk_allocated = 0;
obj = TryToAllocate<kInstrumented, false>(self, allocator, byte_count, &bytes_allocated, &usable_size, &bytes_tl_bulk_allocated);
if (UNLIKELY(obj == nullptr))
// AllocateInternalWithGc can cause thread suspension, if someone instruments the entrypoints or changes the allocator in a suspend point here, we need to retry the allocation.
// TryToAllocate分配失败后调用AllocateInternalWithGc进行分配,会触发gc
obj = AllocateInternalWithGc(self, allocator, kInstrumented, byte_count, &bytes_allocated, &usable_size, &bytes_tl_bulk_allocated, &klass);
if (obj == nullptr)
// The only way that we can get a null return if there is no pending exception is if the allocator or instrumentation changed.
// 无挂起异常的情况下,返回null的唯一情况就是分配器切换或instrumentation变化
if (!self->IsExceptionPending())
// AllocObject will pick up the new allocator type, and instrumented as true is the safe default.
// 无挂起异常,再次重新分配一次吧,使用新的内存分配器
return AllocObject</*kInstrumented*/true>(self, klass, byte_count, pre_fence_visitor);
// 有挂起异常,还是null了,说明内存耗尽了,直接OOM吧
return nullptr;
obj->SetClass(klass);
if (collector::SemiSpace::kUseRememberedSet && UNLIKELY(allocator == kAllocatorTypeNonMoving))
WriteBarrierField(obj, mirror::Object::ClassOffset(), klass);
pre_fence_visitor(obj, usable_size);
QuasiAtomic::ThreadFenceForConstructor();
new_num_bytes_allocated = static_cast<size_t>( num_bytes_allocated_.FetchAndAddRelaxed(bytes_tl_bulk_allocated)) + bytes_tl_bulk_allocated;
// 如果分配器不为kAllocatorTypeBumpPointer、kAllocatorTypeTLAB、kAllocatorTypeRegion、kAllocatorTypeRegionTLAB时,PushOnAllocationStack将把obj保存到self线程对应的数据结构
if (AllocatorHasAllocationStack(allocator))
PushOnAllocationStack(self, &obj);
// check gc
if (AllocatorMayHaveConcurrentGC(allocator) && IsGcConcurrent())
CheckConcurrentGC(self, new_num_bytes_allocated, &obj);
VerifyObject(obj);
self->VerifyStack();
return obj;
// 分配对象内存大小 > 12K,并且对象类型为基础数据数组类型 或者是 字符串类型
inline bool Heap::ShouldAllocLargeObject(mirror::Class* c, size_t byte_count) const
// We need to have a zygote space or else our newly allocated large object can end up in the Zygote resulting in it being prematurely freed.
// We can only do this for primitive objects since large objects will not be within the card table range. This also means that we rely on SetClass not dirtying the object's card.
return byte_count >= large_object_threshold_ && (c->IsPrimitiveArray() || c->IsStringClass());
template <bool kInstrumented, typename PreFenceVisitor>
inline mirror::Object* Heap::AllocLargeObject(Thread* self, mirror::Class** klass, size_t byte_count, const PreFenceVisitor& pre_fence_visitor)
// Save and restore the class in case it moves.
StackHandleScope<1> hs(self);
auto klass_wrapper = hs.NewHandleWrapper(klass);
return AllocObjectWithAllocator<kInstrumented, false, PreFenceVisitor>(self, *klass, byte_count, kAllocatorTypeLOS, pre_fence_visitor);
static ALWAYS_INLINE bool AllocatorHasAllocationStack(AllocatorType allocator_type) Android ART虚拟机 启动和初始化
前言
之前整理了一系列Dalvik虚拟机的关于堆内存和GC的文章,轮到对ART内存进行分析优化了,继续整理输出一波,本篇为ART虚拟机系列的第一篇,介绍ART虚拟机的启动和初始化。
本ART系列基于7.0代码分析。
ART启动
app_main启动
frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
if (zygote)
runtime.start("com.android.internal.os.ZygoteInit", args);
else if (className)
runtime.start("com.android.internal.os.RuntimeInit", args);
else
return 10;
AndroidRuntime.cpp
frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0)
return;
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0)
return;
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
// JNI检测功能,用于native层调用jni函数时进行常规检测,比较弱字符串格式是否符合要求,资源是否正确释放。该功能一般用于早期系统调试或手机Eng版,对于User版往往不会开启,引用该功能比较消耗系统CPU资源,降低系统性能。
bool checkJni = false;
property_get("dalvik.vm.checkjni", propBuf, "");
if (strcmp(propBuf, "true") == 0)
checkJni = true;
else if (strcmp(propBuf, "false") != 0)
property_get("ro.kernel.android.checkjni", propBuf, "");
if (propBuf[0] == '1')
checkJni = true;
if (checkJni)
addOption("-Xcheck:jni");
//虚拟机产生的trace文件,主要用于分析系统问题,路径默认为/data/anr/traces.txt
parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:");
//对于不同的软硬件环境,这些参数往往需要调整、优化,从而使系统达到最佳性能
parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
parseRuntimeOption("dalvik.vm.heaptargetutilization",
heaptargetutilizationOptsBuf, "-XX:HeapTargetUtilization=");
...
//preloaded-classes文件内容是由WritePreloadedClassFile.java生成的,
//在ZygoteInit类中会预加载工作将其中的classes提前加载到内存,以提高系统性能
if (!hasFile("/system/etc/preloaded-classes"))
return -1;
//初始化虚拟机,调用到JniInvocation
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0)
return -1;
JniInvocation.cpp
libnativehelper/JniInvocation.cpp,
5.x的代码里获取libart.so,再获取到JNI_CreateJavaVM、JNI_GetCreatedJavaVMs等的实现。
static const char* kLibraryFallback = "libart.so";
bool JniInvocation::Init(const char* library)
library = GetLibrary(library, buffer);
handle_ = dlopen(library, RTLD_NOW);
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
"JNI_GetDefaultJavaVMInitArgs"))
return false;
if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
"JNI_CreateJavaVM"))
return false;
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
"JNI_GetCreatedJavaVMs"))
return false;
return true;
extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* vm_args)
return JniInvocation::GetJniInvocation().JNI_GetDefaultJavaVMInitArgs(vm_args);
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args)
return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);
extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count)
return JniInvocation::GetJniInvocation().JNI_GetCreatedJavaVMs(vms, size, vm_count);
java_vm_ext.cc
art/runtime/java_vm_ext.cc
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args)
// 虚拟机参数
RuntimeOptions options;
for (int i = 0; i < args->nOptions; ++i)
JavaVMOption* option = &args->options[i];
options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
bool ignore_unrecognized = args->ignoreUnrecognized;
// 创建Runtime对象,它就是虚拟机的化身
if (!Runtime::Create(options, ignore_unrecognized))
return JNI_ERR;
Runtime* runtime = Runtime::Current();
// 启动runtime
runtime->Start();
// 获取JNI ENV和Java VM对象
*p_env = Thread::Current()->GetJniEnv();
*p_vm = runtime->GetJavaVM();
return JNI_OK;
art初始化
art/runtime/runtime.h
art/runtime/runtime.cc
runtime.h
class Runtime
public:
// Creates and initializes a new runtime.
static bool Create(const RuntimeOptions& options, bool ignore_unrecognized)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);
// Starts a runtime, which may cause threads to be started and code to run.
bool Start() UNLOCK_FUNCTION(Locks::mutator_lock_);
static Runtime* Current()
return instance_;
gc::Heap* GetHeap() const
return heap_;
~Runtime();
private:
Runtime();
void BlockSignals();
bool Init(const RuntimeOptions& options, bool ignore_unrecognized)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_);
// A pointer to the active runtime or NULL.
static Runtime* instance_;
gc::Heap* heap_;
Runtime::Create
bool Runtime::Create(const RuntimeOptions& options, bool ignore_unrecognized)
if (Runtime::instance_ != NULL)
return false;
instance_ = new Runtime;
instance_->Init(options, ignore_unrecognized);
return true;
Runtime()
Runtime::Runtime()
: is_zygote_(false),
is_concurrent_gc_enabled_(true),
is_explicit_gc_disabled_(false),
dex2oat_enabled_(true),
default_stack_size_(0),
heap_(nullptr),
monitor_list_(nullptr),
monitor_pool_(nullptr),
thread_list_(nullptr),
class_linker_(nullptr),
signal_catcher_(nullptr),
java_vm_(nullptr)
Runtime::Init
bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized)
// MemMap模块,用于管理内存映射。
// ART大量使用了内存映射技术,比如.oat文件
MemMap::Init();
// 锁实现,和Java中的monitor有关,用于实现线程同步的模块
Monitor::Init(runtime_options.GetOrDefault(Opt::LockProfThreshold), runtime_options.GetOrDefault(Opt::HookIsSensitiveThread));
// 从raw_options转化为runtime_options,获取了n多参数
...
// 维护了一组Monitor对象
monitor_list_ = new MonitorList;
// 用于创建Monitor对象
monitor_pool_ = MonitorPool::Create();
// 用于管理ART中的线程对象,Thread.cpp对象
thread_list_ = new ThreadList;
// 和string intern table有关,即字符串常量池
intern_table_ = new InternTable;
// heap,堆内存了
heap_ = new gc::Heap(xxx);
// 内存池类ArenaPool,可管理多个内存单元Arena
const bool use_malloc = IsAotCompiler();
arena_pool_.reset(new ArenaPool(use_malloc, false));
// 内存分配器LinearAlloc,即可在ArenaPool上分配任意大小的内存
if (IsCompiler() && Is64BitInstructionSet(kRuntimeISA))
// 4gb, no malloc. Explanation in header.
low_4gb_arena_pool_.reset(new ArenaPool(false, true));
linear_alloc_.reset(new LinearAlloc(low_4gb_arena_pool_.get()));
else
linear_alloc_.reset(new LinearAlloc(arena_pool_.get()));
// 和信号处理有关,ART虚拟机进程需要截获来自操作系统的某些信号
BlockSignals();
// 为某些信号设置自定义的信号处理函数
InitPlatformSignalHandlers();
// Always initialize the signal chain so that any calls to sigaction get
// correctly routed to the next in the chain regardless of whether we
// have claimed the signal or not.
InitializeSignalChain();
if (implicit_null_checks_ || implicit_so_checks_ || implicit_suspend_checks_)
// FaultManager,用于处理SIGENV信号
fault_manager.Init();
// 取值为false,启用隐式线程暂停thread suspension检查
if (implicit_suspend_checks_)
new SuspensionHandler(&fault_manager);
// 取值为true,启动隐式堆栈溢出
if (implicit_so_checks_)
new StackOverflowHandler(&fault_manager);
// 取值为true,启动隐式空指针检查
if (implicit_null_checks_)
new NullPointerHandler(&fault_manager);
if (kEnableJavaStackTraceHandler)
new JavaStackTraceHandler(&fault_manager);
// JavaVMExt是JNI中代表Java虚拟机的对象;
// 根据JNI规范,一个进程只有唯一的一个JavaVM对象,对art虚拟机来说,这个JavaVm对象就是此处的java_vm
java_vm_ = new JavaVMExt(this, runtime_options);
// 调用Thread.cpp线程的Startup和Attach方法以初始化虚拟机主线程
Thread::Startup();
Thread* self = Thread::Attach("main", false, nullptr, false);
// 处理和Class有关的工作,解析某个类、寻找某个类、加载某个类
class_linker_ = new ClassLinker(intern_table_);
// 用于检验Java方法的模块,类检验时会用
verifier::MethodVerifier::Init();
// 抛出OutOfMemoryError、NoClassDefFoundError,并清楚,可以理解成清空方法栈吧
self->ThrowNewException("Ljava/lang/OutOfMemoryError;",
"OutOfMemoryError thrown while trying to throw OutOfMemoryError; "
"no stack trace available");
pre_allocated_OutOfMemoryError_ = GcRoot<mirror::Throwable>(self->GetException());
self->ClearException();
self->ThrowNewException("Ljava/lang/NoClassDefFoundError;",
"Class not found using the boot class loader; no stack trace available");
pre_allocated_NoClassDefFoundError_ = GcRoot<mirror::Throwable>(self->GetException());
self->ClearException();
return true;
runtime->start
bool Runtime::Start()
// Restore main thread state to kNative as expected by native code.
Thread* self = Thread::Current();
self->TransitionFromRunnableToSuspended(kNative);
started_ = true;
if (!IsZygote() && jit_options_->UseJIT())
// 加载JNI编译模块对应的so库
CreateJit();
// InitNativeMethods needs to be after started_ so that the classes
// it touches will have methods linked to the oat file if necessary.
// 初始化JNI层相关内容
InitNativeMethods();
// 完成Thread类初始化相关工作
InitThreadGroups(self);
Thread::FinishStartup();
// 创建系统类加载器
system_class_loader_ = CreateSystemClassLoader(this);
// 启动虚拟机的daemon线程
StartDaemonThreads();
finished_starting_ = true;
return true;
以上是关于Android ART虚拟机 对象创建内存分配流程的主要内容,如果未能解决你的问题,请参考以下文章