导语
1.HotSpot内部的各个模块是如何初始化的?
2.类的装载、链接、初始化在HotSpot中是如何完成的?
3.HotSpot如何执行java方法中的字节码?
4.HotSpot如何实现GC?//TODO:
5.HotSpot如何实现JIT编译器?//TODO:
HOTSPOT JVM执行引擎OpenJDK 1.6版本跟1.8版本变化不大,整理了一份index,一是为了梳理思路,二是为了后续查问题可以基于index快速troubleshoot。
一.index
执行引擎代码主要包含三部分:
JVM初始化 : 1.1 main流程
类静态处理 : 1.2 class parse、1.3 class resolve
类方法解释执行 : 1.4 cppInterpreter_zero
1.1 main流程
share/bin/java.c#main
->os\posix\launcher\java_md.c#ContinueInNewThread(创建新线程,执行CreateJavaVM方法,并join到主线程上) -> share\vm\prims\jni.cpp#JNI_CreateJavaVM
->Threads::create_vm
->new JavaThread->set_thread_state(_thread_new),顺便初始化线程的一些存储结构
->runtime\init.cpp#init_globals
->bytecodes_init()初始化bytecode定义
->classLoader_init()设置bootstrapClassLoader搜索路径
->StubRoutines::initialize1(生成部分入口stub_entry)
-><zero>stubGenerator_zero.cpp#StubGenerator_generate || <template>stubGenerator_x86_32.cpp#StubGenerator_generate
->stubGenerator_zero.cpp#generate_initial->StubRoutines::_call_stub_entry=stubGenerator_zero.cpp#call_stub(..)
->universe_init(初始化heap、SymbolTable等)
->Universe::initialize_heap();
->基于gc_policy 设置 Universe::_collectedHeap-> Universe::heap()->initialize()
->SymbolTable::create_table();
->interpreter_init(生成各类方法的解释器函数入口)
->template interpreter
->TemplateInterpreter::initialize
->TemplateTable::initialize()(生成各Bytecodes的汇编函数代码)
->TemplateInterpreterGenerator::generate_all(生成各类型函数的method_entry)
->method_entry(zerolocals) || method_entry(native)
->x86\vm\templateInterpreter_x86_64.cpp#AbstractInterpreterGenerator::generate_method_entry
->templateInterpreter_x86_64.cpp##InterpreterGenerator::generate_normal_entry || generate_native_entry() -> 基于各指令集的assembler生成汇编代码
->zero interpreter
->CppInterpreter::initialize
->stubGenerator_zero.cpp#generate_all
->SharedRuntime::generate_stubs(compiled code to call a (static) C++ runtime routine,好像生成的函数C1或是直接调用会用到,但是代码思路还是很有意思的,值得一看)
->_resolve_virtual_call_blob=SharedRuntime::resolve_virtual_call_C && _resolve_static_call_blob=SharedRuntime::resolve_static_call_C
->runtime/sharedRuntime.cpp#SharedRuntime::resolve_helper()
->SharedRuntime::resolve_sub_helper()
->LinkResolver::resolve_invoke()
->interpreter\linkResolver.cppresolve_invokestatic || resolve_invokevirtual || resolve_invokeinterface
->LinkResolver::resolve_pool()
->LinkResolver::resolve_klass
->constantPoolOop.cpp#constantPoolOopDesc::klass_at_impl(resolve caller常量池中被调用class类,并最终替换常量池Symbol为Klass的直接引用)
->LinkResolver::resolve_virtual_call || LinkResolver::resolve_static_call [TODO://]
->LinkResolver::resolve_virtual_call
->LinkResolver::linktime_resolve_virtual_method(静态 link)
->LinkResolver::runtime_resolve_virtual_method(runtime link)
->LinkResolver::resolve_static_call
->memory\universe.cpp#universe2_init->Universe::genesis()
->初始化Universe中各类通用klass单例,比如klassKlass、methodKlass、constMethodKlass
->vmSymbols::initialize//Symbols提前插入系统常用Symbol,比如常用类、方法、字符串等java/lang/String,<clinit>..
->SystemDictionary::initialize
->SystemDictionary::initialize_preloaded_classes
->SystemDictionary::initialize_wk_klass
->SystemDictionary::_well_known_klasses=SystemDictionary::resolve_or_fail()
->SystemDictionary::resolve_instance_class_or_null[TODO://]
->runtime/jniHandles.cpp#jni_handles_init()
->JNIHandles::_global_handles(static的,说明JNI方法是全局?)
->universe.cpp#universe_post_init
->universe.cpp#_finalizer_register_cache->init()
->Universe::_reflect_invoke_cache->init()
->Universe::_loader_addClass_cache->init()
->Universe::heap()->post_initialize();
->javaClasses.cpp#javaClasses_init->JavaClasses::compute_offsets()(初始化系统类中各个field的offset,可以直接基于内存位置加速读取)
->stubRoutines_init2(跟stubRoutines_init1没有啥差距啊?)
->VMThread::create()
->os::start_thread(vmthread)
->InitializeJavaLangSystem->java_lang_System、java_lang_ThreadGroup、java_lang_Thread等java thread用到的类
->create_initial_thread()
->JavaThread._threadObj=JavaCalls::call_special->java.lang.init(...,"main",...)[#TODO:JavaCalls::call_special函数解析下]
->java_lang_Thread::set_thread_status(thread_object,java_lang_Thread::RUNNABLE);
->java.lang.System#initializeSystemClass
->initialize_class(vmSymbols::java_lang_Compiler())[TODO://compiler相关目前都跳过]
->prims/jni.cpp#quicken_jni_functions()->jni_NativeInterface jni_method_stub初始化,用于JNI的函数指针
->set_init_completed()
->share/bin/java.c#JavaMain
->share/bin/java.c#LoadMainClass()
->a)jdk/src/share/bin/java.c#GetLauncherHelperClass(env)
->b)hotspot/src/share/vm/prims/jni.cpp#get_method_id
->JNIHandles::resolve_non_null(clazz)
->Klass::cast(klass())->initialize(CHECK_NULL);
->klass->lookup_method(name, signature);
->c)CallStaticObjectMethod->vm/prims/jni.cpp#jni_Call##Result##MethodV
->vm/prims/jni.cpp#jni_invoke_static
->[abc4this]sun.launcher.LauncherHelper.checkAndLoadMain
->ClassLoader.getSystemClassLoader().loadClass(var3)
->Launcher.AppClassLoader.getAppClassLoader获取AppClassLoader作为加载器加载main方法
->AppClassLoader.loadClass()
->findLoadedClass->java.lang.ClassLoader.findLoadedClass0->hotspot/src/share/vm/prims/jvm.cpp#JVM_FindLoadedClass->SystemDictionary::find_instance_or_array_klass
->super.loadClass(委托父类加载器加载)
->mainID = (*env)->GetStaticMethodID(env, mainClass, "main","([Ljava/lang/String;)V");//同上
->(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);(执行main方法)
->/vm/prims/jni.cpp#jni_CallStaticVoidMethod
->vm/prims/jni.cpp#jni_invoke_static
->JavaCalls::call
->JavaCalls::call_helper
->address entry_point = method->from_interpreted_entry()
->StubRoutines::call_stub()() 即StubRoutines::_call_stub_entry()
->stubGenerator_x86_32.cpp#generate_call_stub || stubGenerator_zero.cpp#call_stub
->thread->zero_stack()->setup(alloca(zero_stack_size), zero_stack_size)
->EntryFrame::build(parameters, parameter_words, call_wrapper, THREAD)
->set next_frame_off,frame_type_off,call_wrapper_off,parameters
->thread->push_zero_frame(frame);设置thread的frame
->Interpreter::invoke_method(method, entry_point, THREAD);
->oops/methodOop.hpp#_from_interpreted_entry()(切换到解释器方法代码地址开始执行)
->cppInterpreter_zero.cpp#AbstractInterpreterGenerator::generate_method_entry || templateInterpreter_x86_32.cpp#3AbstractInterpreterGenerator::generate_method_entry(本函数入口address是基于method kind赋值的固定地址)
->cppInterpreter_zero.cpp#InterpreterGenerator::generate_normal_entry
->cppInterpreter_zero.cpp#CppInterpreter::normal_entry[GOTO:<cppInterpreter_zero执行引擎流程>]
->result = *(jlong *) stack->sp();(将栈顶缓存作为结果保存下来)
->thread->pop_zero_frame();
->(*vm)->DetachCurrentThread(vm)
->(*vm)->DestroyJavaVM(vm);
1.2 类字节码静态解析
classFileParser.cpp#ClassFileParser::parseClassFile
->u4 magic = cfs->get_u4_fast();
->u2 minor_version = cfs->get_u2_fast();u2 major_version = cfs->get_u2_fast();
->classfile/classFileParser.cpp#ClassFileParser::parse_constant_pool
->constant_pool =oopFactory::new_constantPool(length,oopDesc::IsSafeConc,CHECK_(nullHandle));
->ClassFileParser::parse_constant_pool_entries
->tag->case JVM_CONSTANT_Utf8 || JVM_CONSTANT_Methodref||...//字符串保存到SymbolTable
->access_flags
->this_class_index = cfs->get_u2_fast();//This class
->super_class_index = cfs->get_u2_fast();//superclass,super class的resolve见下
->ClassFileParser::parse_interfaces // Interfaces
->klassOop k = SystemDictionary::resolve_super_or_fail//resolve interface,不太明白起名叫super,接口认为是当前类的super?
->SystemDictionary::resolve_or_null(class_name,class_loader,protection_domain,THREAD)
->SystemDictionary::resolve_instance_class_or_null
->interfaces->obj_at_put(index, interf());//
->ClassFileParser::parse_fields
->typeArrayOop new_fields = oopFactory::new_permanent_shortArray((length + num_injected) * FieldInfo::field_slots, CHECK_(nullHandle));
->access_flags=cfs->get_u2_fast()
->name_index = cfs->get_u2_fast();
->signature_index = cfs->get_u2_fast();
->ClassFileParser::parse_field_attributes //annotation等.
->ClassFileParser::assemble_annotations
->field->initialize()//设置offset
->ClassFileParser::parse_methods
-> objArrayOop m = oopFactory::new_system_objArray(length, CHECK_(nullHandle));
->ClassFileParser::parse_method
->int flags = cfs->get_u2_fast();
->u2 name_index = cfs->get_u2_fast();
->u2 signature_index = cfs->get_u2_fast();
->method_attribute_name_index = cfs->get_u2_fast();method_attribute_length = cfs->get_u4_fast();//Parse code and exceptions attribute
->CASE(:vmSymbols::tag_code())
->ClassFileParser::parse_exception_table
->Parse additional attributes in code attribute
->CASE(:tag_line_number_table)
->ClassFileParser::parse_linenumber_table
->CASE(:tag_local_variable_table)
->ClassFileParser::parse_localvariable_table
->CASE(:vmSymbols::tag_exceptions())
->ClassFileParser::parse_checked_exceptions
->CASE(:vmSymbols::tag_runtime_visible_annotations())
->CASE(:vmSymbols::tag_runtime_visible_annotations())
->methodOop m_oop=oopFactory::new_method(code_length, access_flags, linenumber_table_length,total_lvt_length, checked_exceptions_length,oopDesc::IsSafeConc, CHECK_(nullHandle));
->constMethodOop cm = new_constMethod()
->mk->allocate(cm, access_flags, CHECK_NULL)
->m->set_constants(cp());
->m->set_name_index(name_index);m->set_signature_index(signature_index);m->set_generic_signature_index(generic_signature_index)//generic为未擦除除泛型的
->m->set_size_of_parameters(args_size);
->m->set_max_stack(max_stack);m->set_max_locals(max_locals); // Fill in code attribute information
->// Copy byte codes
->// Copy line number table
->//Copy checked exceptions
->//LocalVariableTable and LocalVariableTypeTable
->assemble_annotations
->method_annotations
->method_parameter_annotations
->method_default_annotations
->methods_annotations//methods_annotations_oop,methods_parameter_annotations_oop,methods_default_annotations_oop
->super_klass=SystemDictionary::resolve_super_or_fail()//resolve super class
->ClassFileParser::compute_transitive_interfaces //父类实现的接口+当前类实现的接口
->super_size = super->transitive_interfaces()->length();
->max_transitive_size += instanceKlass::cast(l)->transitive_interfaces()->length();
->transitive_interfaces = objArrayHandle(THREAD, max_transitive_size);
->classfile/classFileParser.cpp#append_interfaces //将所有接口去重后加入transitive_interfaces
->ClassFileParser::sort_methods//排序当前类的所有method对象
->methodOopDesc::sort_methods
->m->set_method_idnum(i); -> constMethodOopDesc._method_idnum
->oops/klassVtable.cpp#klassVtable::compute_vtable_size_and_num_mirandas //计算vtable大小,包括mirandas方法
->oops/klassVtable.cpp#klassItable::compute_itable_size //所有接口的method都加进来
->visit_all_interfaces(transitive_interfaces(), &cic);
->oop_map
->klassOop ik = oopFactory::new_instanceKlass(name, vtable_size, itable_size,static_field_size,total_oop_map_count,rt, CHECK_(nullHandle)) // 创建instanceKlass
->this_klass->set_access_flags(access_flags);
->this_klass->set_class_loader(class_loader());
->this_klass->set_local_interfaces(local_interfaces());
->this_klass->set_fields(fields(), java_fields_count);
->this_klass->set_methods(methods());
->this_klass->set_constants(cp());
->this_klass->set...
->ClassFileParser::parse_classfile_attributes //vmSymbols::tag_source_file等
->this_klass->set_transitive_interfaces
->oops/klassVtable.cpp#klassItable::setup_itable_offset_table(this_klass);
->klassItable::setup_itable_offset_table
->fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts);
->java_lang_Class::create_mirror(this_klass, CHECK_(nullHandle));
->oops/klassVtable.cpp#visit_all_interfaces
1.3 resolve解决symbol到oop地址的问题
interpreter/linkResolver.cpp#LinkResolver::resolve_invoke
->resolve_invokestatic->LinkResolver::resolve_invokestatic
->LinkResolver::resolve_pool
->LinkResolver::resolve_klass
->oops/constantPoolOop.cpp#constantPoolOopDesc::klass_at_impl
->classfile/systemDictionary.cpp#SystemDictionary::resolve_or_fail(name, instanceKlass::cast(this_oop->pool_holder())->class_loader(), h_prot, true, THREAD);//使用当前前类的class_loader resolve class
->classfile/systemDictionary.cpp#SystemDictionary::resolve_instance_class_or_null
->SystemDictionary._dictionary->find(d_index, d_hash, name, class_loader,protection_domain, THREAD)[注2:]
->placeholder check class loading is in progress
->SystemDictionary::load_instance_class(name, class_loader, THREAD);// Doz actual loading[TODO://]
->JavaCalls::call_virtual(&result,class_loader,spec_klass,vmSymbols::loadClass_name(),vmSymbols::string_class_signature(),string,CHECK_(nh))
->AppClassLoader.loadClass
->java.net.URLClassLoader.findClass
->java.lang.ClassLoader.defineClass1
->lang/ClassLoader.c#Java_java_lang_ClassLoader_defineClass1
->prims/jvm.cpp#jvm_define_class_common
->classfile/systemDictionary.cpp#SystemDictionary::resolve_from_stream
->classfile/classFileParser.cpp#ClassFileParser::parseClassFile[GOTO://<classFileParser.cpp#ClassFileParser::parseClassFile类字节码静态解析>]
->classfile/systemDictionary.cpp#SystemDictionary::define_instance_class//Add class just loaded
->add_to_hierarchy(k, CHECK);//根据R大的说法好像基于此数据结构涉及了个算法加速查找类啥的?具体细节忘了
->SystemDictionary::update_dictionary
->instanceKlass->eager_initialize
->oops/instanceKlass.cpp#instanceKlass::link_class_impl
->link_class_impl(super, throw_verifyerror, CHECK_false);//link super class before linking this class
->link_class_impl(interfaces->obj_at(index), throw_verifyerror, CHECK_false);// link all interfaces implemented by this class before linking this class
->instanceKlass.cpp#instanceKlass::verify_code[TODO://]
->instanceKlass.cpp#instanceKlass::rewrite_class[TODO://]
->instanceKlass.cpp#instanceKlass::relocate_and_link_methods
->interpreter/rewriter.cpp#Rewriter::relocate_and_link[TODO://]
->this_oop->vtable()->initialize_vtable
->oops/klassVtable.cpp#klassVtable::initialize_vtable[TODO://]
->put_method_at(mh(), initialized);
->mh()->set_vtable_index(initialized);
->fill_in_mirandas(initialized);
->klassVtable::put_method_at
->this_oop->itable()->initialize_itable
->oops/klassVtable.cpp#klassItable::initialize_itable[TODO://]
->itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target_h());
->this_oop->set_init_state(linked);//link完成 unparsable_by_gc、allocated、loaded、linked、being_initialized、fully_initialized、initialization_error
->this_oop->resolved_klass_at(which);
->method_name=pool->name_ref_at(index);
->method_signature=pool->signature_ref_at(index);
->LinkResolver::resolve_static_call //resolve 方法
->linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
->interpreter/linkResolver.cpp#LinkResolver::resolve_method
->LinkResolver::lookup_method_in_klasses //lookup method in resolved klass and its super klasses
->oops/instanceKlass.cpp#instanceKlass::uncached_lookup_method
->instanceKlass::cast(klass)->find_method(name, signature)
->method == null -> klass = instanceKlass::cast(klass)->super();
->oops/instanceKlass.cpp#instanceKlass::lookup_method_in_all_interfaces //lookup method in all the interfaces implemented by the resolved klass
->as_klassOop())->transitive_interfaces().map{_.lookup_method(name, signature);}//循环实现接口的方法
->access checks, access checking may be turned off when calling from within the VM.
->resolved_klass->initialize(CHECK);// (link -> fully_initialized)
->oops/instanceKlass.cpp#instanceKlass::initialize -> instanceKlass::initialize_impl
->this_oop->is_initialized()?wait
->this_oop->set_init_state(being_initialized);
->super_klass->initialize()
->instanceKlass::call_class_initializer
->JavaCalls::call(&result, <clinit>, &args, CHECK);//初始化static类
->this_oop->set_initialization_state_and_notify(fully_initialized, CHECK);
->resolve_invokevirtual->LinkResolver::resolve_invokevirtual
->LinkResolver::resolve_pool
->LinkResolver::resolve_virtual_call
->LinkResolver::linktime_resolve_virtual_method
->LinkResolver::resolve_method //同上
->LinkResolver::runtime_resolve_virtual_method
->selected_method=instanceKlass->method_at_vtable(LinkResolver::vtable_index_of_miranda_method(..)) //miranda method
->oops/klassVtable.cpp#klassVtable::index_of_miranda
->selected_method=instanceKlass->method_at_vtable(resolved_method->vtable_index())
->resolve_invokeinterface->LinkResolver::resolve_invokeinterface[TODO://]
->LinkResolver::resolve_pool
->LinkResolver::resolve_interface_call
->LinkResolver::linktime_resolve_interface_method//查找虚函数表,将method_name, method_signature变为resolved_method
->LinkResolver::resolve_interface_method
->LinkResolver::lookup_instance_method_in_klasses// lookup method in this interface or its super, java.lang.Object
->LinkResolver::lookup_method_in_interfaces // lookup method in all the super-interfaces
[TODO://...]
->LinkResolver::runtime_resolve_interface_method
->LinkResolver::lookup_instance_method_in_klasses//查找真正实现此接口的实例
1.4 cppInterpreter_zero执行引擎流程
cppInterpreter_zero.cpp#CppInterpreter::normal_entry
->InterpreterFrame *frame = [BytecodeInterpreter::method_entry>]InterpreterFrame::build(method, CHECK_0)(设置InterpreterFrame,之前的是EntryFrame,EntryFrame是为了对接Interpreter::${MethodKind}_entry)
->thread->push_zero_frame(frame);
->cppInterpreter_zero.cpp#CppInterpreter::main_loop
-while (true) {
->thread->set_last_Java_frame()
->bytecodeInterpreter.cpp#BytecodeInterpreter::run(istate);
->case method_entry: ->goto run
->opcode = *pc;
->switch (opcode)
->CASE(_new)
->method()->constants().slot_at(index).get_oop()->klass_part()
->UseTLAB->THREAD->tlab().allocate(obj_size);
->Atomic::cmpxchg_ptr(new_top, Universe::heap()->top_addr(), compare_to)(指针碰撞在eden区分配)
->UseBiasedLocking->result->set_mark(如果启用偏向锁,则设置markword)
->Slow case allocation:InterpreterRuntime::_new
->instanceKlass.cpp#instanceKlass::allocate_instance
->instanceKlass.cpp#CollectedHeap::obj_allocate
->CollectedHeap::obj_allocate[TODO://<instance初始化>:]
->CASE(_invokevirtual || _invokespecial || _invokestatic)
->InterpreterRuntime::resolve_invoke
->thread->last_frame().interpreter_callee_receiver(signature)//首先基于Interpreter上的bcp找到获取到bci,然后基于bic就能获取到被调用者的signature,然后基于栈顶缓存获取receiver对象,即extract receiver
->interpreter/linkResolver.cpp#LinkResolver::resolve_invoke//caller constantPool method resolve[TODO://方法内用到的method使用此种方式加载]
->cache_entry(thread)->set_method(bytecode,info.resolved_method(),info.vtable_index())
->istate->set_msg(call_method);
->callee = (methodOop) rcvrKlass->start_of_vtable()[ cache->f2()];//取出receiver instanceKlass的虚函数表相应位置的callee methodOop;
->istate->set_callee(callee);
->istate->set_callee_entry_point(callee->from_interpreted_entry());
->istate->set_bcp_advance(3);
->UPDATE_PC_AND_RETURN
->CASE(_invokeinterface)
->InterpreterRuntime::resolve_invoke//接口时
->thread->last_frame().interpreter_callee_receiver(signature)//同上_invokevirtual
->interpreter/linkResolver.cpp#LinkResolver::resolve_invoke
->int index = klassItable::compute_itable_index(info.resolved_method()());//设置缓存itable的index
->klassItable::compute_itable_index
->instanceKlass::cast(intf)->methods()//计算method归属接口类的index[TODO://interface]
->cache_entry(thread)->set_interface_call(info.resolved_method(), index);
->istate->set_msg(call_method);
->instanceKlass->start_of_itable()->interface_klass()//查找当前方法归属接口类
->instanceKlass->start_of_itable().first_method_entry(rcvr->klass()).[cache->f2()].method();
->CASE(_return)->handle_return
->Check all the monitors(暂时pass)
->istate->set_msg(return_from_method);
->istate->set_return_kind((Bytecodes::Code)opcode);
->CASE(_athrow)(抛异常会降低性能?具体影响程度感兴趣的时候再读)
->if istate->msg() == BytecodeInterpreter::call_method
->methodOop callee = istate->callee();
->Interpreter::invoke_method(callee, istate->callee_entry_point(), THREAD);
->CppInterpreter::normal_entry(重新回到解释器入口函数,构建新的frame,并依次执行方法内bytecode)
->InterpreterFrame *frame = [BytecodeInterpreter::method_entry>]InterpreterFrame::build(method, CHECK_0)
->thread->push_zero_frame(frame);
->cppInterpreter_zero.cpp#CppInterpreter::main_loop
->istate->set_msg(BytecodeInterpreter::method_resume);
->if istate->msg() == BytecodeInterpreter::return_from_method
->Copy the result into the caller's frame
->跳出循环break;[GOTO:Break]
->//end while (true)
->[Break]thread->pop_zero_frame();
->stack->push(res);//结果写到栈帧上
简写注释:
bci(bytecode_index),index指在常量池中的索引
bcp(bytecode_pointer:instruction pointer)
二.reference
- http://hllvm.group.iteye.com/group/forum
- https://gbenson.net/
- https://www.cnblogs.com/WCFGROUP/p/6511485.html
- 揭秘Java虚拟机:JVM设计原理与实现
五一假期3天时间review了一下OpenJDK1.6 执行引擎的代码,之前定的目标,目前来看只实现了前3个,由于汇编、操作系统、硬件指令集基础太差,Interpreter主要看的zero来替代
TemplateInterpreter
来串联思路,gc、jit目前暂时不看了:gc后续再看了,这个还是要搞明白的,JIT这个难度太大了,无限期延后了。
网友评论