|
在类的连接之前要保证对类进行了解析,例如初始化一个类时会调用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
|
|