类文件解析006

编程入门 行业动态 更新时间:2024-10-11 21:27:25

类<a href=https://www.elefans.com/category/jswz/34/1771438.html style=文件解析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

本文发布于:2024-02-25 04:53:45,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1697870.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:文件

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!