之前在介绍类的双亲委派机制时,多次涉及到对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()函数等,在后面涉及相关知识点时将详细介绍这些方法的实现。