文件解析006"/>
类文件解析006
本文来介绍一下解析接口的部分,这部分的代码比较简单,算是为了给之后解析变量内容的减压.
为了内容的连贯性,先来看一下class文件的格式:
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count; --> 在调用ClassFileParser::parse_constant_pool时ClassFileStream的指针就指向这里
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];
}
对接口涉及到的字段说明如下:
-
interfaces_count
接口计数器,interfaces_count的值表示当前类或接口的直接父接口数量。
-
interfaces[]
接口表,interfaces[]数组中的每个成员的值必须是一个对constant_pool表中项目的一个有效索引值,它的长度为interfaces_count。每个成员interfaces[i] 必须为CONSTANT_Class_info类型常量,其中0 ≤ i < interfaces_count。在interfaces[]数组中,成员所表示的接口顺序和对应的源代码中给定的接口顺序(从左至右)一样,即interfaces[0]对应的是源代码中最左边的接口。
解析
本文所涉及的代码如下:
// Interfaces 7. 读取接口信息,接口类型包括本地接口和父类传递接口
u2 itfs_len = cfs->get_u2_fast();
objArrayHandle local_interfaces;
if (itfs_len == 0) {// 7.1 如果接口不存在,则返回一个空数组local_interfaces = objArrayHandle(THREAD, Universe::the_empty_system_obj_array());
} else {// 7.2 解析接口local_interfaces = parse_interfaces(cp, itfs_len, class_loader, protection_domain, _class_name, CHECK_(nullHandle));
}
此时,需要注意的是,如果是没有接口的话,则会复用之前实例化的空数组(这个数组是在Universe::genesis(TRAPS) 方法中创建的,在类加载流程003, 类加载流程004 中有介绍 ).
接下来,我们来看一下ClassFileParser::parse_interfaces,其代码如下:
objArrayHandle ClassFileParser::parse_interfaces(constantPoolHandle cp,int length,Handle class_loader,Handle protection_domain,symbolHandle class_name,TRAPS) {ClassFileStream* cfs = stream();assert(length > 0, "only called for length>0");// 1. 在内存中分配长度为length 的 数组objArrayHandle nullHandle;objArrayOop interface_oop = oopFactory::new_system_objArray(length, CHECK_(nullHandle));objArrayHandle interfaces (THREAD, interface_oop);int index;// 2. 依次进行解析for (index = 0; index < length; index++) {// 2.1 进行验证,1<= interface_index < interfaces_count,并且常量池中interface_index的必须是CONSTANT_Class_info类型常量u2 interface_index = cfs->get_u2(CHECK_(nullHandle));KlassHandle interf;check_property(valid_cp_range(interface_index, cp->length()) &&is_klass_reference(cp, interface_index),"Interface name has bad constant pool index %u in class file %s",interface_index, CHECK_(nullHandle));// 2.2 如果interface_index所对应的类,已经加载过,则直接使用即可if (cp->tag_at(interface_index).is_klass()) {interf = KlassHandle(THREAD, cp->resolved_klass_at(interface_index));} else {// 2.3 如果没有加载过,则进行加载symbolHandle unresolved_klass (THREAD, cp->klass_name_at(interface_index));// Don't need to check legal name because it's checked when parsing constant pool.// But need to make sure it's not an array type.// 2.3.1 不需要检查其名字格式是否正确,因为其在解析常量池时已经检查过了.但是需要检查其不是数组类型guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY,"Bad interface name in class file %s", CHECK_(nullHandle));// Call resolve_super so classcircularity is checked// 2.3.2 进行解析klassOop k = SystemDictionary::resolve_super_or_fail(class_name,unresolved_klass, class_loader, protection_domain,false, CHECK_(nullHandle));interf = KlassHandle(THREAD, k);if (LinkWellKnownClasses) // my super type is well known to mecp->klass_at_put(interface_index, interf()); // eagerly resolve}// 2.4 如果不是接口,则抛出异常if (!Klass::cast(interf())->is_interface()) {THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", nullHandle);}// 2.5 保存到数组中interfaces->obj_at_put(index, interf());}// 3.1 如果不需要验证或者接口的长度为1,则不需要进行重复接口的交易if (!_need_verify || length <= 1) {return interfaces;}// Check if there's any duplicates in interfaces 检查是否有重复的接口ResourceMark rm(THREAD);NameSigHash** interface_names = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, NameSigHash*, HASH_ROW_SIZE);initialize_hashtable(interface_names);bool dup = false;{debug_only(No_Safepoint_Verifier nsv;)for (index = 0; index < length; index++) {klassOop k = (klassOop)interfaces->obj_at(index);symbolOop name = instanceKlass::cast(k)->name();// If no duplicates, add (name, NULL) in hashtable interface_names.if (!put_after_lookup(name, NULL, interface_names)) {dup = true;break;}}}if (dup) {// 3.2 如果有重复的接口,则抛出异常classfile_parse_error("Duplicate interface name in class file %s",CHECK_(nullHandle));}return interfaces;
}
注释写的比较详细,流程简单,这里就不再展开了.
更多推荐
类文件解析006
发布评论