|  | 在类的连接之前要保证对类进行了解析,例如初始化一个类时会调用initialize_class()方法,实现如下: | static void initialize_class(Symbol* class_name, TRAPS) { Klass* klass = SystemDictionary::resolve_or_fail(class_name, true, CHECK);
 InstanceKlass::cast(klass)->initialize(CHECK);
 }
 | 
 在类的初始化过程中,首先要调用SystemDictionary::resolve_or_fail()方法保证类被正确装载,如果类没有被装载,那么最终会调用到ClassFileParser::parseClassFile()方法装载类,并通过创建ConstantPool、Method、InstanceKlass等对象将元数据保存到HotSpot中。然后在调用的initialize()方法中会间接调用InstanceKlass::link_class_impl()方法进行类的连接。InstanceKlass::link_class_impl()方法的实现如下:
 
 
 | bool InstanceKlass::link_class_impl(instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS) { 
 // return if already verified
 //  通过_init_state属性的值来判断类是否已经验证过
 if (this_oop->is_linked()) {
 return true;
 }
 
 JavaThread* jt = (JavaThread*)THREAD;
 
 // 在连接子类之前先连接父类
 // link super class before linking this class
 instanceKlassHandle  super(THREAD, this_oop->super());
 if (super.not_null()) {
 if (super->is_interface()) {  // check if super class is an interface
 return false;
 }
 
 link_class_impl(super, throw_verifyerror, CHECK_false); // 递归调用此方法进行连接操作
 }
 
 // 连接该类实现的所有接口
 // link all interfaces implemented by this class before linking this class
 Array<Klass*>* interfaces = this_oop->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_oop->is_linked()) {
 return true;
 }
 
 
 // verification & rewriting 验证和重写
 {
 oop           init_lock = this_oop->init_lock();
 ObjectLocker  ol(init_lock, THREAD, init_lock != NULL);
 // rewritten will have been set if loader constraint error found
 // on an earlier link attempt
 // don't verify or rewrite if already rewritten
 
 if (!this_oop->is_linked()) {
 if (!this_oop->is_rewritten()) {
 {
 // 进行字节码验证
 bool verify_ok = verify_code(this_oop, throw_verifyerror, THREAD);
 if (!verify_ok) {
 return false;
 }
 }
 // Just in case a side-effect of verify linked this class already
 // (which can sometimes happen since the verifier loads classes
 // using custom class loaders, which are free to initialize things)
 // 可能有时候会在验证的过程中导致类已经被连接,不过并不会进行类的初始化
 if (this_oop->is_linked()) {
 return true;
 }
 // 重写类
 // also sets rewritten
 this_oop->rewrite_class(CHECK_false);
 } // end rewritten
 
 // 完成类的重写后进行方法连接
 // relocate jsrs and link methods after they are all rewritten
 this_oop->link_methods(CHECK_false);
 
 // Initialize the vtable and interface table after
 // methods have been rewritten since rewrite may fabricate(编造; 捏造) new Method*s.
 // also does loader constraint checking
 // 初始化vtable和itable
 if (!this_oop()->is_shared()) {
 ResourceMark rm(THREAD);
 klassVtable* kv = this_oop->vtable();
 kv->initialize_vtable(true, CHECK_false);
 
 klassItable* ki = this_oop->itable();
 ki->initialize_itable(true, CHECK_false);
 }
 
 // 将类的状态标记为已连接状态
 this_oop->set_init_state(linked);
 }// end linked
 
 }// end  verification & rewriting
 
 return true;
 }
 | 
 方法的逻辑非常清晰,我们可以很容易读懂类的连接过程,步骤总结如下:
 
 连接父类和实现的接口。因为根据虚拟机规范,子类的初始化必然会导致父类的初始化,所以子类在连接之前自然要保证父类已经连接;
 -进行字节码验证;
 -重写类;
 -连接方法;
 -初始化vtable和itable;
 -将类的状态标记为已连接。
 
 大概的执行逻辑如下图所示。
 
 
   
 在连接类之前需要判断此类是否已经连接,之前介绍过,每个InstanceKlass中都定义了一个_init_state属性,如下:
 
 
 | u1  _init_state;    // state of class | 
 值只能为ClassState枚举类中定义的枚举常量,如下:
 
 
 | // See "The Java Virtual Machine Specification" section 2.16.2-5 for a detailed description // of the class loading & initialization procedure, and the use of the states.
 enum ClassState {
 allocated,            // allocated (but not yet linked)
 loaded,               // loaded and inserted in class hierarchy (but not linked yet)
 linked,               // successfully linked/verified (but not initialized yet)  连接包括验证、准备和解析阶段
 being_initialized,    // currently running class initializer
 fully_initialized,    // initialized (successfull final state)
 initialization_error  // error happened during initialization
 };
 | 
 这些状态主要标注一个类的加载、连接和初始化状态,3个过程已经在虚拟机规范中有了明确的规定,参考地址为https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html。
 
 allocated状态表示已经分配内存,在InstanceKlass的构造函数中通常会将_init_state初始化为这个状态。
 
 loaded状态表示类已经装载并且已经插入到继承体系中,在 SystemDictionary::add_to_hierarchy()方法中会更新InstanceKlass的_init_state状态。
 
 linked状态表示已经成功连接/校验,只在InstanceKlass::link_class_impl()方法中更新为这个状态。
 
 另外3个状态是在类的初始化方法InstanceKlass::initialize_impl()中会使用,后面也会介绍到。
 
 
 
 
 程序猿的技术大观园:www.javathinker.net
 |  |