HotSpot 类解析
上一篇了解了Java字节码文件组织结构,继HotSpot类加载后本篇来探讨HotSpot类解析。Java字节码文件是以二进制流的形式由HotSpot加载,然后HotSpot将字节码解析转换成虚拟机内部的对象模型。并将这个对象模型存储在虚拟机的元空间供虚拟机引擎重复使用。所以关于类解析有三个问题:类如何被解析,对象模型是什么样的,元空间(MetaSpace)的存储结构。在类加载一篇我们知道字节码的二进制流由ClassFileStream加载到内存,然后由ClassFileParser解析。
一,HotSpot内部对象模型
Java类在虚拟机内部的对象模型定义在oops目录下,模型主要定义了与Java语言相关的模型结构,是Java面向对象特征在虚拟机中的映射。在模型树描述中主要由klass,oop,metadata,handle来组织(klass继承自metadata)。
Oop模型
Java对象在虚拟机中的表示
hotspot/src/share/vm/oops/oopsHierarchy.hpp
//java对象中oop的偏移量而
typedef juint narrowOop;
// 如果压缩klass指针,则使用窄klass
typedef juint narrowKlass;
typedef void* OopOrNarrowOopStar;
//对象头标记
typedef class markOopDesc* markOop;#ifndef CHECK_UNHANDLED_OOPS//对象头(包含markOop),包含Kclass
typedef class oopDesc* oop;
//Java类实例对象(包含oop)
typedef class instanceOopDesc* instanceOop;
//Java数组(包含oop)
typedef class arrayOopDesc* arrayOop;
//Java对象数组(包含arrayOop)
typedef class objArrayOopDesc* objArrayOop;
//Java基本类型数组(包含arrayOop)
typedef class typeArrayOopDesc* typeArrayOop;#else
Klass模型
Java类在虚拟机中的表示
hotspot/src/share/vm/oops/oopsHierarchy.hpp
// klass层次结构与oop层次结构是分开的。//继承自 Metadata, 维护着类继承结构的类信息,对应一个ClassLoaderData
class Klass;
//继承自Klass,维护着对应的Java类相关信息(注解,字段,接口,虚表,版本,线程等信息),以及类所处的状 态
class InstanceKlass;
//继承自InstanceKlass,用于java.lang.Class实例,与反射相关,除了类的普通字段之外,它们还包含类的静态字段
class InstanceMirrorKlass;
//继承自InstanceKlass,它是为了遍历这个类装入器指向的类装入器的依赖关系。
class InstanceClassLoaderKlass;
//继承自InstanceKlass,与java/lang/ref/Reference相关
class InstanceRefKlass;
//继承自Klass,数组相关
class ArrayKlass;
//继承自ArrayKlass,对象数组
class ObjArrayKlass;
//继承自ArrayKlass,基本类型数组
class TypeArrayKlass;
MetaData模型
虚拟机元数据
hotspot/src/share/vm/oops/oopsHierarchy.hpp
// 元数据层次结构与oop层次结构是分开的// class MetaspaceObj
//继承自MetaspaceObj,方法信息相关,参数,返回值,注解,异常,code指令
class ConstMethod;
//继承自MetaspaceObj,包含ConstantPool
class ConstantPoolCache;
//继承自Metadata,与方法统计优化有关
class MethodData;
// class Metadata
//继承自Metadata,组织方法有关信息,包含ConstMethod,MethodData,MethodData,CompiledMethod等
class Method;
//继承自Metadata,包含Java类字节码常量池信息
class ConstantPool;
// class CHeapObj
//继承自CHeapObj,包含方法的编译等信息
class CompiledICHolder;
Handle模型
持有其他三种模型的引用,相比直接访问其他三种模型效率偏低,但是灵活性好
hotspot/src/share/vm/runtime/handles.hpp
//OopHandle
DEF_HANDLE(instance , is_instance_noinline )
DEF_HANDLE(array , is_array_noinline )
DEF_HANDLE(objArray , is_objArray_noinline )
DEF_HANDLE(typeArray , is_typeArray_noinline )
//KlassHandle
class KlassHandle : public StackObj {Klass* _value;......
}
//MetadateHandle
DEF_METADATA_HANDLE(method, Method)
DEF_METADATA_HANDLE(constantPool, ConstantPool)
二,HotSpot元空间(MetaSpace)
元空间取代了PermSpace,主要用于存储类的Klass和其他非Class信息。元空间的初始化在universe_init()阶段执行的
1.元空间初始化
hotspot/src/share/vm/memory/universe.cpp
jint universe_init() {Metaspace::global_initialize();
}
hotspot/src/share/vm/memory/metaspace.cpp
主要初始化了VirtualSpaceList和ChunkManager
void Metaspace::global_initialize() {MetaspaceGC::initialize();......// Initialize the list of virtual spaces._space_list = new VirtualSpaceList(word_size);_chunk_manager_metadata = new ChunkManager(SpecializedChunk, SmallChunk, MediumChunk);......
}
hotspot/src/share/vm/memory/universe.cpp
元空间的初始化是在universe2_init ()阶段执行的
void universe2_init() {EXCEPTION_MARK;Universe::genesis(CATCH);
}
初始化了SpaceManager和第一个Chunk
void Metaspace::initialize(Mutex* lock, MetaspaceType type) {verify_global_initialization();// Allocate SpaceManager for metadata objects._vsm = new SpaceManager(NonClassType, lock);if (using_class_space()) {// Allocate SpaceManager for classes._class_vsm = new SpaceManager(ClassType, lock);}// Allocate chunk for metadata objectsinitialize_first_chunk(type, NonClassType);// Allocate chunk for class metadata objectsif (using_class_space()) {initialize_first_chunk(type, ClassType);}
}
2.元空间组织结构
现在元空间中出现了三个组织元素ChunkManager,SpaceManager,VirtualSpaceList。它们按如下规则组织元空间
1.SpaceManager提供了对外内存分配释放的接口。
2.VirtualSpaceNode是VirtualSpaceList的一个节点每个节点代表着一个ReservedSpace和VirtualSpace。负责Chunk分配。
3.MetaChunk是VirtualSpace上一段连续的内存。
4.Metablock是从Metachunk中分配内存的单位。
5.BlockFreelist管理着所有的空闲MetaBlock。
6.ChunkManager维护着元空间中所有的MetaChunk,MetaChunk的使用归还都需要在此记录。
三,类解析
hotspot/src/share/vm/classfile/klassFactory.cpp
instanceKlassHandle KlassFactory::create_from_stream(......){//解析类ClassFileParser parser(stream,name,loader_data, protection_domain,host_klass,cp_patches,ClassFileParser::BROADCAST, CHECK_NULL);//创建HandleinstanceKlassHandle result = parser.create_instance_klass(old_stream != stream, CHECK_NULL);
}
hotspot/src/share/vm/classfile/classFileParser.cpp
ClassFileParser::ClassFileParser(ClassFileStream* stream,Symbol* name, ClassLoaderData* loader_data,Handle protection_domain,const InstanceKlass* host_klass,GrowableArray<Handle>* cp_patches, Publicity pub_level, TRAPS) :_stream(stream),_requested_name(name),_loader_data(loader_data),_host_klass(host_klass),_cp_patches(cp_patches),......stream->set_verify(_need_verify); //设置类验证标志parse_stream(stream, CHECK); //解析字节码流post_process_parsed_stream(stream, _cp, CHECK);}
hotspot/src/share/vm/classfile/classFileParser.cpp
classFileStream中维护着_current变量,记录当前解析位置。类,父类,接口,字段,方法,属性等信息解析都离不开常量池。
void ClassFileParser::parse_stream(const ClassFileStream* const stream,TRAPS){//取cafebabe魔数const u4 magic = stream->get_u4_fast();//主次版本号_minor_version = stream->get_u2_fast();_major_version = stream->get_u2_fast();//常量池大小const u2 cp_size = stream->get_u2_fast();//ConstantPool为对象模型_cp = ConstantPool::allocate(_loader_data,cp_size, CHECK);//解析常量池parse_constant_pool(stream, cp, cp_size, CHECK);//类权限标志jint flags;// JVM_ACC_MODULE is defined in JDK-9 and later.if (_major_version >= JAVA_9_VERSION) {flags = stream->get_u2_fast() & (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_MODULE);} else {flags = stream->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS;}//当前类_this_class_index = stream->get_u2_fast();//从常量池中取类信息Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index);_class_name = class_name_in_cp;//父类_super_class_index = stream->get_u2_fast();//解析父类_super_klass = parse_super_class(cp, _super_class_index, _need_verify,CHECK);//接口_itfs_len = stream->get_u2_fast();//解析接口parse_interfaces(stream,_itfs_len,cp, &_has_nonstatic_concrete_methods, CHECK);//类字段解析_fac = new FieldAllocationCount();parse_fields(stream, _access_flags.is_interface(), _fac, cp,cp_size,&_java_fields_count, CHECK);//类方法解析AccessFlags promoted_flags;parse_methods(stream, _access_flags.is_interface(),&promoted_flags,&_has_final_method,&_declares_nonstatic_concrete_methods,CHECK);//类属性解析_parsed_annotations = new ClassAnnotationCollector();parse_classfile_attributes(stream, cp, _parsed_annotations, CHECK);create_combined_annotations(CHECK);}
1. 常量池解析
hotspot/src/share/vm/classfile/classFileParser.cpp
常量池解析后会将常量池信息缓存到ConstantPool对象模型当中
void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream,ConstantPool* const cp,const int length,TRAPS) {//1.解析常量池数据存储到ConstantPool中,缓存一级解析结果parse_constant_pool_entries(stream, cp, length, CHECK);//2.解析常量池数据,做二次解析,缓存常量池二级索引解析的结果for (index = 1; index < length; index++) { // Index 0 is unusedconst jbyte tag = cp->tag_at(index).value();......}//3.根据校验标志校验if (!_need_verify) {return;}for (index = 1; index < length; index++) {const jbyte tag = cp->tag_at(index).value();......}
}
hotspot/src/share/vm/classfile/classFileParser.cpp
一级索引解析,缓存解析结果到常量池
void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream,ConstantPool* cp,const int length,TRAPS) {const ClassFileStream cfs1 = *stream;const ClassFileStream* const cfs = &cfs1;// Used for batching symbol allocations.const char* names[SymbolTable::symbol_alloc_batch_size];int lengths[SymbolTable::symbol_alloc_batch_size];int indices[SymbolTable::symbol_alloc_batch_size];unsigned int hashValues[SymbolTable::symbol_alloc_batch_size];int names_count = 0;// parsing Index 0 is unusedfor (int index = 1; index < length; index++) {const u1 tag = cfs->get_u1_fast(); //常量池存储tag类型switch (tag) {case JVM_CONSTANT_Class : { //类信息cfs->guarantee_more(3, CHECK); // name_index, tag/access_flagsconst u2 name_index = cfs->get_u2_fast(); //类名索引cp->klass_index_at_put(index, name_index);//暂存在常量池对象模型当中break;}case JVM_CONSTANT_Fieldref: {//字段cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flagsconst u2 class_index = cfs->get_u2_fast(); //所属类索引const u2 name_and_type_index = cfs->get_u2_fast();//字段信息索引cp->field_at_put(index, class_index, name_and_type_index);break;}case JVM_CONSTANT_Methodref: {//方法cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flagsconst u2 class_index = cfs->get_u2_fast();//所属类索引const u2 name_and_type_index = cfs->get_u2_fast();//方法信息索引cp->method_at_put(index, class_index, name_and_type_index);break;}case JVM_CONSTANT_InterfaceMethodref: {//接口方法cfs->guarantee_more(5, CHECK); // class_index, name_and_type_index, tag/access_flagsconst u2 class_index = cfs->get_u2_fast();//所属接口索引const u2 name_and_type_index = cfs->get_u2_fast();//方法信息索引cp->interface_method_at_put(index, class_index, name_and_type_index);break;}case JVM_CONSTANT_String : { //字符串信息cfs->guarantee_more(3, CHECK); // string_index, tag/access_flagsconst u2 string_index = cfs->get_u2_fast(); //字符串索引cp->string_index_at_put(index, string_index); break;}case JVM_CONSTANT_MethodHandle : //方法句柄类型决定字节码行为case JVM_CONSTANT_MethodType: {if (tag == JVM_CONSTANT_MethodHandle) {cfs->guarantee_more(4, CHECK); // ref_kind, method_index, tag/access_flagsconst u1 ref_kind = cfs->get_u1_fast(); //const u2 method_index = cfs->get_u2_fast();cp->method_handle_index_at_put(index, ref_kind, method_index);}else if (tag == JVM_CONSTANT_MethodType) {cfs->guarantee_more(3, CHECK); // signature_index, tag/access_flagsconst u2 signature_index = cfs->get_u2_fast();cp->method_type_index_at_put(index, signature_index);}break;}case JVM_CONSTANT_InvokeDynamic : { //动态调用const u2 bootstrap_specifier_index = cfs->get_u2_fast();const u2 name_and_type_index = cfs->get_u2_fast();if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index) {_max_bootstrap_specifier_index = (int) bootstrap_specifier_index; // collect for later}cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index);break;}case JVM_CONSTANT_Integer: { //基本类型cfs->guarantee_more(5, CHECK); // bytes, tag/access_flagsconst u4 bytes = cfs->get_u4_fast();cp->int_at_put(index, (jint)bytes);break;}case JVM_CONSTANT_Float: { cfs->guarantee_more(5, CHECK); // bytes, tag/access_flagsconst u4 bytes = cfs->get_u4_fast();cp->float_at_put(index, *(jfloat*)&bytes);break;}case JVM_CONSTANT_Long: {// A mangled type might cause you to overrun allocated memoryguarantee_property(index + 1 < length,"Invalid constant pool entry %u in class file %s",index,CHECK);cfs->guarantee_more(9, CHECK); // bytes, tag/access_flagsconst u8 bytes = cfs->get_u8_fast();cp->long_at_put(index, bytes);index++; // Skip entry following eigth-byte constant, see JVM book p. 98break;}case JVM_CONSTANT_Double: {// A mangled type might cause you to overrun allocated memoryguarantee_property(index+1 < length,"Invalid constant pool entry %u in class file %s",index,CHECK);cfs->guarantee_more(9, CHECK); // bytes, tag/access_flagsconst u8 bytes = cfs->get_u8_fast();cp->double_at_put(index, *(jdouble*)&bytes);index++; // Skip entry following eigth-byte constant, see JVM book p. 98break;}case JVM_CONSTANT_NameAndType: {cfs->guarantee_more(5, CHECK); // name_index, signature_index, tag/access_flagsconst u2 name_index = cfs->get_u2_fast();const u2 signature_index = cfs->get_u2_fast();cp->name_and_type_at_put(index, name_index, signature_index);break;}case JVM_CONSTANT_Utf8 : { //编码码点u2 utf8_length = cfs->get_u2_fast(); //字节长度const u1* utf8_buffer = cfs->get_u1_buffer(); //......cp->symbol_at_put(index, result);break;}case 19: //模块case 20: { //包信息if (_major_version >= JAVA_9_VERSION) {cfs->guarantee_more(3, CHECK);cfs->get_u2_fast();set_class_bad_constant_seen(tag);break;}}default: {break;}} // end of switch(tag)} // end of for// 分配符号表if (names_count > 0) {SymbolTable::new_symbols(_loader_data,cp, names_count,names,lengths,indices,hashValues,CHECK);}// Copy _current pointer of local copy back to stream.assert(stream->current() == old_current, "non-exclusive use of stream");stream->set_current(cfs1.current());}
2.接口解析
hotspot/src/share/vm/classfile/classFileParser.cpp
接口解析会验证接口是否加载过,如果没有则加载,解析结果在_local_interfaces
void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,const int itfs_len,ConstantPool* const cp,bool* const has_nonstatic_concrete_methods,TRAPS) {if (itfs_len == 0) {_local_interfaces = Universe::the_empty_klass_array();} else {_local_interfaces = MetadataFactory::new_array<Klass*>(_loader_data, itfs_len, NULL, CHECK);int index;for (index = 0; index < itfs_len; index++) {const u2 interface_index = stream->get_u2(CHECK);KlassHandle interf;if (cp->tag_at(interface_index).is_klass()) {interf = KlassHandle(THREAD, cp->resolved_klass_at(interface_index));} else {Symbol* const unresolved_klass = cp->klass_name_at(interface_index);// 加载接口const Klass* const k =SystemDictionary::resolve_super_or_fail(_class_name,unresolved_klass,_loader_data->class_loader(),_protection_domain,false,CHECK);interf = KlassHandle(THREAD, k);}if (InstanceKlass::cast(interf())->has_nonstatic_concrete_methods()) {*has_nonstatic_concrete_methods = true;}_local_interfaces->at_put(index, interf());}if (!_need_verify || itfs_len <= 1) {return;}
}
3. 类字段解析
hotspot/src/share/vm/classfile/classFileParser.cpp
字段信息解析到FiledInfo模型中
void ClassFileParser::parse_fields(const ClassFileStream* const cfs,bool is_interface,FieldAllocationCount* const fac,ConstantPool* cp,const int cp_size,u2* const java_fields_count_ptr,TRAPS) {const u2 length = cfs->get_u2_fast(); //字段信息长度*java_fields_count_ptr = length;int num_injected = 0;const InjectedField* const injected = JavaClasses::get_injected(_class_name,&num_injected);const int total_fields = length + num_injected;u2* const fa = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, u2,total_fields * (FieldInfo::field_slots + 1));// The generic signature slots start after all other fields' data.int generic_signature_slot = total_fields * FieldInfo::field_slots;int num_generic_signature = 0;for (int n = 0; n < length; n++) {// access_flags, name_index, descriptor_index, attributes_countcfs->guarantee_more(8, CHECK);//访问权限AccessFlags access_flags;const jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_FIELD_MODIFIERS;verify_legal_field_modifiers(flags, is_interface, CHECK);access_flags.set_flags(flags);//字段类型索引const u2 name_index = cfs->get_u2_fast();const Symbol* const name = cp->symbol_at(name_index);verify_legal_field_name(name, CHECK);//字段名索引const u2 signature_index = cfs->get_u2_fast();const Symbol* const sig = cp->symbol_at(signature_index);verify_legal_field_signature(name, sig, CHECK);//字段信息u2 constantvalue_index = 0;bool is_synthetic = false;u2 generic_signature_index = 0;const bool is_static = access_flags.is_static();FieldAnnotationCollector parsed_annotations(_loader_data);//属性解析const u2 attributes_count = cfs->get_u2_fast();if (attributes_count > 0) {parse_field_attributes(cfs,attributes_count,is_static,signature_index,&constantvalue_index,&is_synthetic,&generic_signature_index,&parsed_annotations,CHECK);//字段初始化FieldInfo* const field = FieldInfo::from_field_array(fa, n);field->initialize(access_flags.as_short(),name_index,signature_index,constantvalue_index);_fields =MetadataFactory::new_array<u2>(_loader_data,index * FieldInfo::field_slots + num_generic_signature,CHECK);// Sometimes injected fields already exist in the Java source so// the fields array could be too long. In that case the// fields array is trimed. Also unused slots that were reserved// for generic signature indexes are discarded.{int i = 0;for (; i < index * FieldInfo::field_slots; i++) {_fields->at_put(i, fa[i]);}for (int j = total_fields * FieldInfo::field_slots;j < generic_signature_slot; j++) {_fields->at_put(i++, fa[j]);}assert(_fields->length() == i, "");}
}
4.方法解析
hotspot/src/share/vm/classfile/classFileParser.cpp
void ClassFileParser::parse_methods(const ClassFileStream* const cfs,bool is_interface,AccessFlags* promoted_flags,bool* has_final_method,bool* declares_nonstatic_concrete_methods,TRAPS) {cfs->guarantee_more(2, CHECK); // lengthconst u2 length = cfs->get_u2_fast(); //方法数量if (length == 0) {_methods = Universe::the_empty_method_array();} else {_methods = MetadataFactory::new_array<Method*>(_loader_data, length,NULL,CHECK);for (int index = 0; index < length; index++) {//解析方法Method* method = parse_method(cfs,is_interface,_cp,promoted_flags,CHECK);if (method->is_final()) {*has_final_method = true;}// declares_nonstatic_concrete_methods: declares concrete instance methods, any access flags// used for interface initialization, and default method inheritance analysisif (is_interface && !(*declares_nonstatic_concrete_methods)&& !method->is_abstract() && !method->is_static()) {*declares_nonstatic_concrete_methods = true;}_methods->at_put(index, method);}}
}
hotspot/src/share/vm/classfile/classFileParser.cpp
将字节码中的方法信息解析到Method和ConstMethod模型中
Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,bool is_interface,const ConstantPool* cp, AccessFlags* const promoted_flags,TRAPS) {//......省略一大堆解析//创建Method模型Method* const m = Method::allocate(_loader_data,code_length,access_flags,&sizes,ConstMethod::NORMAL,CHECK_NULL);ClassLoadingService::add_class_method_size(m->size()*wordSize);//向模型中填充方法信息m->set_constants(_cp);m->set_name_index(name_index);m->set_signature_index(signature_index);ResultTypeFinder rtf(cp->symbol_at(signature_index));m->constMethod()->set_result_type(rtf.type());if (args_size >= 0) {m->set_size_of_parameters(args_size);} else {m->compute_size_of_parameters(THREAD);}// 填充代码属性信息m->set_max_stack(max_stack);m->set_max_locals(max_locals);if (stackmap_data != NULL) {m->constMethod()->copy_stackmap_data(_loader_data,(u1*)stackmap_data,stackmap_data_length,CHECK_NULL);}// 复制方法中的code指令m->set_code((u1*)code_start);//行号表//异常表//方法参数if (method_parameters_length > 0) {MethodParametersElement* elem = m->constMethod()->method_parameters_start();for (int i = 0; i < method_parameters_length; i++) {elem[i].name_cp_index = Bytes::get_Java_u2((address)method_parameters_data);method_parameters_data += 2;elem[i].flags = Bytes::get_Java_u2((address)method_parameters_data);method_parameters_data += 2;}}//类本地变量if (total_lvt_length > 0) {promoted_flags->set_has_localvariable_table();copy_localvariable_table(m->constMethod(),lvt_cnt,localvariable_table_length,localvariable_table_start,lvtt_cnt,localvariable_type_table_length,localvariable_type_table_start,CHECK_NULL);}if (parsed_annotations.has_any_annotations())parsed_annotations.apply_to(m);//拷贝注解信息copy_method_annotations(m->constMethod(),runtime_visible_annotations,runtime_visible_annotations_length,runtime_invisible_annotations,runtime_invisible_annotations_length,runtime_visible_parameter_annotations,runtime_visible_parameter_annotations_length,runtime_invisible_parameter_annotations,runtime_invisible_parameter_annotations_length,runtime_visible_type_annotations,runtime_visible_type_annotations_length,runtime_invisible_type_annotations,runtime_invisible_type_annotations_length,annotation_default,annotation_default_length,CHECK_NULL);if (name == vmSymbols::finalize_method_name() &&signature == vmSymbols::void_method_signature()) {if (m->is_empty_method()) {_has_empty_finalizer = true;} else {_has_finalizer = true;}}if (name == vmSymbols::object_initializer_name() &&signature == vmSymbols::void_method_signature() &&m->is_vanilla_constructor()) {_has_vanilla_constructor = true;}NOT_PRODUCT(m->verify());return m;
}
5.属性解析
过于繁杂,不再列出。
6.虚表和mirandas处理
hotspot/src/share/vm/classfile/classFileParser.cpp
void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const stream, ConstantPool* cp,TRAPS) {// 确保父类解析if (_super_class_index > 0 && NULL ==_super_klass) {Symbol* const super_class_name = cp->klass_name_at(_super_class_index);if (_access_flags.is_interface()) {_super_klass = (const InstanceKlass*)SystemDictionary::resolve_super_or_fail(_class_name,super_class_name,_loader_data->class_loader(),_protection_domain,true,CHECK);}// 计算是否全部实现接口方法_transitive_interfaces = compute_transitive_interfaces(_super_klass, _local_interfaces,_loader_data,CHECK);//排序方法_method_ordering = sort_methods(_methods);_all_mirandas = new GrowableArray<Method*>(20);//计算虚表和mirandas方法klassVtable::compute_vtable_size_and_num_mirandas(&_vtable_size,&_num_miranda_methods,_all_mirandas,_super_klass, _methods,_access_flags,_major_version,_loader_data->class_loader(),_class_name,_local_interfaces,CHECK);// 虚表大小_itable_size = _access_flags.is_interface() ? 0 :klassItable::compute_itable_size(_transitive_interfaces);//字段内存优化_field_info = new FieldLayoutInfo();layout_fields(cp, _fac, _parsed_annotations, _field_info, CHECK);// Compute reference typ_rt = (NULL ==_super_klass) ? REF_NONE : _super_klass->reference_type();
}
7.创建InstanceKclass模型
hotspot/src/share/vm/classfile/classFileParser.cpp
InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, TRAPS) {if (_klass != NULL) {return _klass;}//创建对象InstanceKlass* const ik = InstanceKlass::allocate_instance_klass(*this, CHECK_NULL);//填充信息到Kclassfill_instance_klass(ik, changed_by_loadhook, CHECK_NULL);return ik;
}
hotspot/src/share/vm/oops/instanceKlass.cpp
根据解析结果创建InstanceKlass模型,关联kclass到类加载器,在元空间分配内存,存储InstanceKlass模型
InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) {.....const Symbol* const class_name = parser.class_name();ClassLoaderData* loader_data = parser.loader_data();InstanceKlass* ik;// Allocationif (REF_NONE == parser.reference_type()) {if (class_name == vmSymbols::java_lang_Class()) {// mirrorik = new (loader_data, size, THREAD) InstanceMirrorKlass(parser);}else if (is_class_loader(class_name, parser)) {// class loaderik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(parser);}else {// normalik = new (loader_data, size, THREAD) InstanceKlass(parser, InstanceKlass::_misc_kind_other);}}else {// referenceik = new (loader_data, size, THREAD) InstanceRefKlass(parser);}const bool publicize = !parser.is_internal();//关联kclass到类加载器loader_data->add_class(ik, publicize);Atomic::inc(&_total_instanceKlass_count);return ik;
}
hotspot/src/share/vm/oops/klass.cpp
向MetaSpace申请分配内存
void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw() {return Metaspace::allocate(loader_data, word_size, /*read_only*/false,MetaspaceObj::ClassType, THREAD);
}
hotspot/src/share/vm/memory/metaspace.cpp
元空间中由SpaceManager作为内存分配对外接口
MetaWord* SpaceManager::allocate(size_t word_size) {MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);size_t raw_word_size = get_allocation_word_size(word_size);BlockFreelist* fl = block_freelists();MetaWord* p = NULL;if (fl != NULL && fl->total_size() > allocation_from_dictionary_limit) {p = fl->get_block(raw_word_size);}if (p == NULL) {p = allocate_work(raw_word_size);}return p;
}
四,类链接和初始化
hotspot/src/share/vm/classfile/systemDictionary.cpp
类解析结束后还不能使用,还需要链接和初始化
instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {if (k.is_null()) {//加载类k = ClassLoader::load_class(class_name, search_only_bootloader_append, CHECK_(nh));}
}
if (!k.is_null()) {instanceKlassHandle defined_k = find_or_define_instance_class(class_name, class_loader, k, THREAD);return k;
}
hotspot/src/share/vm/classfile/systemDictionary.cpp
instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* class_name, Handle class_loader, instanceKlassHandle k, TRAPS) {//.....define_instance_class(k, THREAD);//......
}
hotspot/src/share/vm/classfile/systemDictionary.cpp
void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) {k->eager_initialize(THREAD);
}
hotspot/src/share/vm/classfile/systemDictionary.cpp
初始化类
void InstanceKlass::eager_initialize(Thread *thread) {if (!EagerInitialization) return;if (this->is_not_initialized()) {eager_initialize_impl(this_k); }
}
hotspot/src/share/vm/oops/instanceKlass.cpp
链接类
void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_k) {link_class_impl(this_k, true, THREAD);
}
hotspot/src/share/vm/oops/instanceKlass.cpp
链接接口方法,类方法等等
bool InstanceKlass::link_class_impl(instanceKlassHandle this_k, bool throw_verifyerror, TRAPS) {// return if already verifiedif (this_k->is_linked()) {return true;}JavaThread* jt = (JavaThread*)THREAD;// 链接接口实现Array<Klass*>* interfaces = this_k->local_interfaces();int num_interfaces = interfaces->length();for (int index = 0; index < num_interfaces; index++) {HandleMark hm(THREAD);instanceKlassHandle ih(THREAD, interfaces->at(index));link_class_impl(ih, throw_verifyerror, CHECK_false);}// in case the class is linked in the process of linking its superclassesif (this_k->is_linked()) {return true;}// 验证和重写{//先锁定oop init_lock = this_k->init_lock();ObjectLocker ol(init_lock, THREAD, init_lock != NULL);if (!this_k->is_linked()) { //未链接if (!this_k->is_rewritten()) {//未重写{bool verify_ok = verify_code(this_k, throw_verifyerror, THREAD);if (!verify_ok) {return false;}}if (this_k->is_linked()) {return true;}// also sets rewrittenthis_k->rewrite_class(CHECK_false);} else if (this_k->is_shared()) {SystemDictionaryShared::check_verification_constraints(this_k, CHECK_false);}//链接方法this_k->link_methods(CHECK_false);//初始化虚表和接口ClassLoaderData * loader_data = this_k->class_loader_data();if (!(this_k->is_shared() &&loader_data->is_the_null_class_loader_data())) {ResourceMark rm(THREAD);this_k->vtable()->initialize_vtable(true, CHECK_false);this_k->itable()->initialize_itable(true, CHECK_false);}//设置这状态this_k->set_init_state(linked);if (JvmtiExport::should_post_class_prepare()) {Thread *thread = THREAD;JvmtiExport::post_class_prepare((JavaThread *) thread, this_k());}}}return true;
}
虚拟机将字节码文件以流的形式加载到内存中,再将字节码文件各信息组合成虚拟机需要的对象模型和内存模型存储到MateSpace中。最后初始化对象模型,以备使用,依照对象模型,虚拟机可以按指令在堆中创建无数有限个对象。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
