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 objects
  initialize_first_chunk(type, NonClassType);

  // Allocate chunk for class metadata objects
  if (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);
    //创建Handle
   instanceKlassHandle 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 unused
    const 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 unused
  for (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_flags
        const 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_flags
        const 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_flags
        const 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_flags
        const 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_flags
        const 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_flags
          const 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_flags
          const 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_flags
        const 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_flags
        const 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 memory
        guarantee_property(index + 1 < length,
                           "Invalid constant pool entry %u in class file %s",
                           index,
                           CHECK);
        cfs->guarantee_more(9, CHECK);  // bytes, tag/access_flags
        const u8 bytes = cfs->get_u8_fast();
        cp->long_at_put(index, bytes);
        index++;   // Skip entry following eigth-byte constant, see JVM book p. 98
        break;
      }
      case JVM_CONSTANT_Double: {
        // A mangled type might cause you to overrun allocated memory
        guarantee_property(index+1 < length,
                           "Invalid constant pool entry %u in class file %s",
                           index,
                           CHECK);
        cfs->guarantee_more(9, CHECK);  // bytes, tag/access_flags
        const u8 bytes = cfs->get_u8_fast();
        cp->double_at_put(index, *(jdouble*)&bytes);
        index++;   // Skip entry following eigth-byte constant, see JVM book p. 98
        break;
      }
      case JVM_CONSTANT_NameAndType: {
        cfs->guarantee_more(5, CHECK);  // name_index, signature_index, tag/access_flags
        const 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_count
    cfs->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);  // length
  const 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 analysis
      if (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);
  //填充信息到Kclass
  fill_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;
  // Allocation
  if (REF_NONE == parser.reference_type()) {
    if (class_name == vmSymbols::java_lang_Class()) {
      // mirror
      ik = new (loader_data, size, THREAD) InstanceMirrorKlass(parser);
    }
    else if (is_class_loader(class_name, parser)) {
      // class loader
      ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(parser);
    }
    else {
      // normal
      ik = new (loader_data, size, THREAD) InstanceKlass(parser, InstanceKlass::_misc_kind_other);
    }
  }
  else {
    // reference
    ik = 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 verified
  if (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 superclasses
  if (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 rewritten
        this_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中。最后初始化对象模型,以备使用,依照对象模型,虚拟机可以按指令在堆中创建无数有限个对象。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值