类文件介绍

2021-04-07 11:36:57 浏览数 (2)

之前在介绍类的双亲委派机制时,多次涉及到对ClassFileParser类中的parseClassFile()的调用。因为类的装载不仅仅是找到类对应的Class文件二进制流,更要解析出Class文件中包含的信息,将其转换为C/C 表示方式,这样虚拟机在运行过程中才能更方便的进行操作。

在介绍parseClassFile()方法之前,先认识一下Java虚拟机规范定义的Class文件格式及ClassFileParse类中定义的一些重要属性。

类文件的格式如下:

代码语言:javascript复制
ClassFile {
    u4             magic;

    u2             minor_version;
    u2             major_version;

    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];

    u2             access_flags;
    u2             this_class;
    u2             super_class;

    u2             interfaces_count;
    u2             interfaces[interfaces_count];

    u2             fields_count;
    field_info     fields[fields_count];

    u2             methods_count;
    method_info    methods[methods_count];

    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

这个相对简单,目前说明这个格式的参考资料也比较多,这里不做过多介绍。 

HotSpot定义了ClassFileParser类来辅助读取及保存类解析的相关信息,类及重要属性的定义如下:

代码语言:javascript复制
源代码位置:src/share/vm/classfile/classLoader.hpp
class ClassFileParser VALUE_OBJ_CLASS_SPEC {
 private:
  u2        _major_version;
  u2        _minor_version;
  Symbol*   _class_name;
  ClassLoaderData*         _loader_data;
  KlassHandle              _host_klass;
  GrowableArray<Handle>*   _cp_patches; // overrides for CP entries


  // class attributes parsed before the instance klass is created:
  bool        _synthetic_flag;
  int         _sde_length;
  char*       _sde_buffer;
  u2          _sourcefile_index;
  u2          _generic_signature_index;

  // Metadata created before the instance klass is created.  Must be deallocated
  // if not transferred to the InstanceKlass upon successful class loading
  // in which case these pointers have been set to NULL.
  instanceKlassHandle _super_klass;
  ConstantPool*    _cp;
  Array<u2>*       _fields;
  Array<Method*>*  _methods;
  Array<u2>*       _inner_classes;
  Array<Klass*>*   _local_interfaces;
  Array<Klass*>*   _transitive_interfaces;
  // ...
  InstanceKlass*   _klass;  // InstanceKlass once created.
  …
  ClassFileStream* _stream;              // Actual input stream
  ...
}

类中的属性通过名称就可以知道存储的相关信息,其中最主要的就是通过_cp保存常量池信息、通过_fields保存域信息、通过_methods保存方法、通过_klass保存类相关的信息。通过_stream属性可以方便地读取流的信息,在下一篇将详细介绍。

类还定义了许多重要的函数,例如解析常量池的parse_constant_pool()与parse_constant_pool_entries()函数、解析方法的parse_methods()函数、解析字段的parse_fields()函数等,在后面涉及相关知识点时将详细介绍这些方法的实现。 

0 人点赞