赞
踩
来源
7.0之前ART只有AOT模式,7.0之后采用解释、JIT、AOT混合执行。方法调用有如下几种流程:
机器码–>机器码
机器码–>解释
解释–>解释
解释–>机器码
java方法在ART虚拟机中以ArtMethod表示,其中entry_point_from_quick_compiled_code_保存的是方法的入口地址,在类加载的LinkCode()函数中设置入口地址。
基本执行流程
java方法在ART虚拟机中以ArtMethod表示,其中entry_point_from_quick_compiled_code_保存的是方法的入口地址,在类加载的LinkCode()函数中设置入口地址。
class ArtMethod {
struct PtrSizedFields {
void* data_;//与JNI有关
void* entry_point_from_quick_compiled_code_;//java方法入口函数地址
} ptr_sized_fields_;
};
从zygote启动创建虚拟机环境后,通过AndroidRuntime::start()开始进入java世界,如下代码调用的就是com.android.internal.os.ZygoteInit类的静态成员函数main。
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
env->CallStaticVoidMethod是一个函数指针,经验证实际指向jni_internal.cc::CallStaticVoidMethodV()函数,如下会进一步调用到ArtMethod的Invoke()方法。
1.static void CallStaticVoidMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args)
2.JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid,
va_list args)
3.void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa,
ArtMethod* method, ArgArray* arg_array, JValue* result,
const char* shorty)
4.method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, shorty);
Invoke()方法最终调用到汇编代码art_quick_invoke_stub_internal,汇编又进一步跳转到ART_METHOD_QUICK_CODE_OFFSET_32偏移,根据定义可知,该偏移正是ArtMethod对象中的成员变量entry_point_from_compiled_code_,由此真正开始进入java方法。
void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result,
const char* shorty) {
if (!IsStatic()) {
(*art_quick_invoke_stub)(this, args, args_size, self, result, shorty);
} else {
(*art_quick_invoke_static_stub)(this, args, args_size, self, result, shorty);
}
}
1.void art_quick_invoke_stub(ArtMethod* method, uint32_t* args, uint32_t args_size,
Thread* self, JValue* result, const char* shorty)
2.void art_quick_invoke_static_stub(ArtMethod* method, uint32_t* args,
uint32_t args_size, Thread* self, JValue* result,
const char* shorty)
template <bool kIsStatic>
3.static void quick_invoke_reg_setup(ArtMethod* method, uint32_t* args, uint32_t args_size,
Thread* self, JValue* result, const char* shorty)
4.void art_quick_invoke_stub_internal(ArtMethod*, uint32_t*, uint32_t,
Thread* self, JValue* result, uint32_t, uint32_t*,
uint32_t*);
art/runtime/arch/arm/quick_entrypoints_arm.S:
ENTRY art_quick_invoke_stub_internal
SPILL_ALL_CALLEE_SAVE_GPRS @ spill regs (9)
ldr ip, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32] @ get pointer to the code
blx ip @ call the method
END art_quick_invoke_stub_internal
art/runtime/generated/asm_support_gen.h:
#define ART_METHOD_QUICK_CODE_OFFSET_32 24
DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_QUICK_CODE_OFFSET_32), (static_cast<int32_t>(art::ArtMethod::EntryPointFromQuickCompiledCodeOffset(art::PointerSize::k32).Int32Value())))
如上述介绍,通过com.android.internal.os.ZygoteInit::main类、方法字符串信息,最终查找到方法的ArtMethod对象,并通过entry_point_from_compiled_code_开始执行方法对应的指令。
设置entry_point_from_compiled_code_是在Class_Linker.cc::LinkCode()完成的,由于虚拟机执行情况复杂,解释、static、JNI等执行情况,entry_point_from_compiled_code_并不直接指向AOT编译的机器码,而是指向一段Trampoline代码来间接执行。
static void LinkCode(ClassLinker* class_linker, ArtMethod* method, const OatFile::OatClass* oat_class, uint32_t class_def_method_index) REQUIRES_SHARED(Locks::mutator_lock_) { if (oat_class != nullptr) { //设置entry_point_from_compiled_code_为OAT编译生成的机器码地址 const OatFile::OatMethod oat_method = oat_class->GetOatMethod(class_def_method_index); oat_method.LinkMethod(method); } const void* quick_code = method->GetEntryPointFromQuickCompiledCode(); //机器码地址为空或者是调试状态等,需要解释模式 bool enter_interpreter = class_linker->ShouldUseInterpreterEntrypoint(method, quick_code); if (method->IsStatic() && !method->IsConstructor()) { //静态方法且不是类初始化"<clinit>"方法,设置入口地址为art_quick_resolution_trampoline //跳转到artQuickResolutionTrampoline函数。该函数和类的解析有关 //初始化完毕后会调用FixupStaticTrampolines()来更新入口地址为正确的机器码。 method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionStub()); } else if (quick_code == nullptr && method->IsNative()) { //jni方法,设置入口地址为art_quick_generic_jni_trampoline,跳转到artQuickGenericJniTrampoline函数。 method->SetEntryPointFromQuickCompiledCode(GetQuickGenericJniStub()); } else if (enter_interpreter) { //解释执行,设置入口地址为art_quick_to_interpreter_bridge,跳转到artQuickToInterpreterBridge函数。 method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge()); } //jni方法,设置ArtMethod ptr_sized_fields_.data为art_jni_dlsym_lookup_stub,跳转到artFindNativeMethod函数。 if (method->IsNative()) { method->UnregisterNative(); } }
Trampoline函数:artQuickToInterpreterBridge
上述有4种Trampoline函数,我们以机器码–>解释过程为例介绍artQuickToInterpreterBridge。
art/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc:
uint64_t artQuickToInterpreterBridge(ArtMethod* method, Thread* self, ArtMethod** sp) { ManagedStack fragment;//栈管理相关 //A->B,不是代理方法的话,non_proxy_method 就是被调用的ArtMethod* B本身。 ArtMethod* non_proxy_method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize); CodeItemDataAccessor accessor(non_proxy_method->DexInstructionData()); const char* shorty = non_proxy_method->GetShorty(&shorty_len); JValue result; if (UNLIKELY(deopt_frame != nullptr)) { ...//HDeoptimize相关,暂不关注 } else { //创建ArtMethod* B的栈帧shadow_frame ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr = CREATE_SHADOW_FRAME(num_regs, /* link */ nullptr, method, /* dex pc */ 0); ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get(); size_t first_arg_reg = accessor.RegistersSize() - accessor.InsSize(); //借助BuildQuickShadowFrameVisitor将调用参数放到shadow_frame对象中 BuildQuickShadowFrameVisitor shadow_frame_builder(sp, method->IsStatic(), shorty, shorty_len, shadow_frame, first_arg_reg); shadow_frame_builder.VisitArguments(); //判断ArtMethod* B所属类是否初始化 const bool needs_initialization = method->IsStatic() && !method->GetDeclaringClass()->IsInitialized(); //栈管理相关 self->PushManagedStackFragment(&fragment); self->PushShadowFrame(shadow_frame); //初始化,类初始化就是调用ClassLinker的EnsureInitialized函数。 if (needs_initialization) { StackHandleScope<1> hs(self); Handle<mirror::Class> h_class(hs.NewHandle(shadow_frame->GetMethod()->GetDeclaringClass())); if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) { self->PopManagedStackFragment(fragment); return 0; } } //解释执行的入口函数 result = interpreter::EnterInterpreterFromEntryPoint(self, accessor, shadow_frame); } //栈管理相关 self->PopManagedStackFragment(fragment); return result.GetJ(); }
art/runtime/interpreter/interpreter.cc:
JValue EnterInterpreterFromEntryPoint(Thread* self, const CodeItemDataAccessor& accessor,
ShadowFrame* shadow_frame) {
//JIT相关
jit::Jit* jit = Runtime::Current()->GetJit();
if (jit != nullptr) {
jit->NotifyCompiledCodeToInterpreterTransition(self, shadow_frame->GetMethod());
}
//关键函数
return Execute(self, accessor, *shadow_frame, JValue());
}
解释执行的实现方式有2种,由kInterpreterImplKind的值控制:
kMterpImplKind:根据不同CPU平台,采用汇编语言实现。默认值。
kSwitchImplKind :由C++编写,基于switch/case实现。
static inline JValue Execute( Thread* self, const CodeItemDataAccessor& accessor, ShadowFrame& shadow_frame, JValue result_register, bool stay_in_interpreter = false) REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* method = shadow_frame.GetMethod(); //transaction_active 和dex2oat有关,完整虚拟机返回false。 bool transaction_active = Runtime::Current()->IsActiveTransaction(); if (LIKELY(method->SkipAccessChecks())) { if (kInterpreterImplKind == kMterpImplKind) { //汇编实现 ExecuteMterpImpl(self, accessor.Insns(), &shadow_frame, &result_register); } else { //C++ switch/case实现 return ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame, result_register, false); } } }
ExecuteSwitchImplCpp处理逻辑非常工整,一种dex指令对应switch中的一种case。
art/runtime/interpreter/interpreter_switch_impl.cc:
void ExecuteSwitchImplCpp(SwitchImplContext* ctx) { //dex_pc指向要执行的dex指令 uint32_t dex_pc = shadow_frame.GetDexPC(); //insns代表方法的dex指令码数组 const uint16_t* const insns = accessor.Insns(); const Instruction* inst = Instruction::At(insns + dex_pc); uint16_t inst_data; do { //遍历dex指令码数组 dex_pc = inst->GetDexPc(insns); shadow_frame.SetDexPC(dex_pc); TraceExecution(shadow_frame, inst, dex_pc); inst_data = inst->Fetch16(0); //针对每一种dex指令处理。每种dex之前,都有一个PREAMBLE宏,就是调用instrumentation的DexPcMovedEvent函数。 switch (inst->Opcode(inst_data)) { case Instruction::NOP: PREAMBLE(); inst = inst->Next_1xx(); break; case Instruction::INVOKE_DIRECT: { PREAMBLE(); //调用DoInvoke bool success = DoInvoke<kDirect, false, do_access_check>( self, shadow_frame, inst, inst_data, &result_register); POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); break; } } while (!interpret_one_instruction); //记录dex指令执行的位置,并更新到shadow_frame中 shadow_frame.SetDexPC(inst->GetDexPc(insns)); ctx->result = result_register; return; }
DoInvoke是一个模板函数,能处理invoke-direct/static/super/virtual/interface等指令。
现在我们处于方法B中,接下来看B如何调用C,对应ArtMethod* C。
template<InvokeType type, bool is_range, bool do_access_check> static inline bool DoInvoke(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data, JValue* result) { //method_idx为方法c在dex文件里method_ids数组中的索引 const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c(); //找到方法c对应的对象。它作为参数存储在方法B的ShadowFrame对象中。 const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c(); ObjPtr<mirror::Object> receiver = (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC); //sf_method代表ArtMethod* B ArtMethod* sf_method = shadow_frame.GetMethod(); //FindMethodFromCode查找目标方法c对应的ArtMethod对象,即ArtMethod* C。 ArtMethod* const called_method = FindMethodFromCode<type, do_access_check>( method_idx, &receiver, sf_method, self); if (UNLIKELY(called_method == nullptr)) { } else if (UNLIKELY(!called_method->IsInvokable())) { } else { ... return DoCall<is_range, do_access_check>(called_method, self, shadow_frame, inst, inst_data, result); } }
DoCall又进一步调用DoCallCommon。
art/runtime/interpreter/interpreter_common.cc:
template <bool is_range, bool do_assignability_check> static inline bool DoCallCommon(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame, JValue* result, uint16_t number_of_inputs, uint32_t (&arg)[Instruction::kMaxVarArgRegs], uint32_t vregC) { //创建方法c所需的ShadowFrame对象 ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr = CREATE_SHADOW_FRAME(num_regs, &shadow_frame, called_method, /* dex pc */ 0); ShadowFrame* new_shadow_frame = shadow_frame_unique_ptr.get(); if (do_assignability_check) { ...//不考虑此种情况 } else { //从B的ShadowFrame中拷贝C所需参数到C的ShadowFrame对象中 CopyRegisters<is_range>(shadow_frame, new_shadow_frame, arg, vregC, first_dest_reg, number_of_inputs); } //跳转到方法C PerformCall(self, accessor, shadow_frame.GetMethod(), first_dest_reg, new_shadow_frame, result, use_interpreter_entrypoint); return !self->IsExceptionPending(); }
art/runtime/common_dex_operations.h:
inline void PerformCall(Thread* self, const CodeItemDataAccessor& accessor, ArtMethod* caller_method, const size_t first_dest_reg, ShadowFrame* callee_frame, JValue* result, bool use_interpreter_entrypoint) REQUIRES_SHARED(Locks::mutator_lock_) { if (LIKELY(Runtime::Current()->IsStarted())) { if (use_interpreter_entrypoint) { //解释模式,debug或者机器码不存在,调用ArtInterpreterToInterpreterBridge interpreter::ArtInterpreterToInterpreterBridge(self, accessor, callee_frame, result); } else { //以机器码执行方法C,调用ArtInterpreterToCompiledCodeBridge interpreter::ArtInterpreterToCompiledCodeBridge( self, caller_method, callee_frame, first_dest_reg, result); } } else { interpreter::UnstartedRuntime::Invoke(self, accessor, callee_frame, result, first_dest_reg); } }
art/runtime/interpreter/interpreter.cc:
void ArtInterpreterToInterpreterBridge(Thread* self,
const CodeItemDataAccessor& accessor,
ShadowFrame* shadow_frame,
JValue* result) {
self->PushShadowFrame(shadow_frame);//栈管理相关
EnsureInitialized();//static的话,是否初始化
if (LIKELY(!shadow_frame->GetMethod()->IsNative())) {
//如果不是JNI方法,调用Execute执行。又回到上述描述调用流程。
result->SetJ(Execute(self, accessor, *shadow_frame, JValue()).GetJ());
}
self->PopShadowFrame();//栈管理相关
}
art/runtime/interpreter/interpreter_common.cc:
void ArtInterpreterToCompiledCodeBridge(Thread* self,
ArtMethod* caller,
ShadowFrame* shadow_frame,
uint16_t arg_offset,
JValue* result)
REQUIRES_SHARED(Locks::mutator_lock_) {
ArtMethod* method = shadow_frame->GetMethod();
EnsureInitialized();//static的话,是否初始化
//又回到上述调用流程,Invoke最终调用到entry_point_from_quick_compiled_code_
method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset),
(shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t),
result, method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty());
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。