重庆企业型网站建设,深圳网站设计公司有哪些,免费微信快速开发平台,网站背景色代码第25章-类的初始化
这一章主要是讲类的初始化操作#xff0c;后续类加载章节中也会用到这一章的知识#xff0c;只不过#xff0c;这里就讲#xff0c;是因为虚拟在初始化过程中#xff0c;需要对基础类#xff0c;比如System/Thread等类进行初始化操作#xff0c;所以…第25章-类的初始化
这一章主要是讲类的初始化操作后续类加载章节中也会用到这一章的知识只不过这里就讲是因为虚拟在初始化过程中需要对基础类比如System/Thread等类进行初始化操作所以就提前把这块内容先讲掉。
调用链
thread.cpp-create_vm()
// 这里只摘取了部分代码
initialize_class(vmSymbols::java_lang_String(), CHECK_0);// Initialize java_lang.System (needed before creating the thread)
initialize_class(vmSymbols::java_lang_System(), CHECK_0);
initialize_class(vmSymbols::java_lang_ThreadGroup(), CHECK_0);thread.cpp-initialize_class(Symbol* class_name, TRAPS)
static void initialize_class(Symbol* class_name, TRAPS) {Klass* klass SystemDictionary::resolve_or_fail(class_name, true, CHECK);InstanceKlass::cast(klass)-initialize(CHECK);
}instanceKlass.cpp-InstanceKlass::initialize
void InstanceKlass::initialize(TRAPS) {if (this-should_be_initialized()) {HandleMark hm(THREAD);instanceKlassHandle this_oop(THREAD, this);initialize_impl(this_oop, CHECK); // 真正的初始化操作在这里看章节25.1// Note: at this point the class may be initialized// OR it may be in the state of being initialized// in case of recursive initialization!} else {assert(is_initialized(), sanity check);}
}25.1 类的初始化
25.1.1 instanceKlass.cpp
25.1.1.1 initialize_impl
函数中总共分成11个步骤来完成这11个步骤在Java虚拟机规范文档中有描述下面我们看看初始化时到底做了啥
void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {// Make sure klass is linked (verified) before initialization// A class could already be verified, since it has been reflected upon.this_oop-link_class(CHECK);DTRACE_CLASSINIT_PROBE(required, InstanceKlass::cast(this_oop()), -1);bool wait false;// refer to the JVM book page 47 for description of steps// Step 1{// 步骤1初始化之前通过 ObjectLocker 对初始化操作加锁防止多线程同步问题oop init_lock this_oop-init_lock();ObjectLocker ol(init_lock, THREAD, init_lock ! NULL);Thread *self THREAD; // its passed the current thread// Step 2// 步骤2正在初始化的线程不是当前线程那么释放获取到的锁同时当前线程进入阻塞状态等待其他线程完成初始化操作while(this_oop-is_being_initialized() !this_oop-is_reentrant_initialization(self)) {wait true;ol.waitUninterruptibly(CHECK);}// Step 3// 步骤3正在初始化的线程就是当前线程那就表明这是对初始化的递归请求释放锁if (this_oop-is_being_initialized() this_oop-is_reentrant_initialization(self)) {DTRACE_CLASSINIT_PROBE_WAIT(recursive, InstanceKlass::cast(this_oop()), -1,wait);return;}// Step 4// 步骤4已经初始化完成那就不做什么直接释放锁并返回if (this_oop-is_initialized()) {DTRACE_CLASSINIT_PROBE_WAIT(concurrent, InstanceKlass::cast(this_oop()), -1,wait);return;}// Step 5// 步骤5初始化过程出现错误那就直接抛出异常 java_lang_NoClassDefFoundErrorif (this_oop-is_in_error_state()) {DTRACE_CLASSINIT_PROBE_WAIT(erroneous, InstanceKlass::cast(this_oop()), -1,wait);ResourceMark rm(THREAD);const char* desc Could not initialize class ;const char* className this_oop-external_name();size_t msglen strlen(desc) strlen(className) 1;char* message NEW_RESOURCE_ARRAY(char, msglen);if (NULL message) {// Out of memory: cant create detailed error messageTHROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className);} else {jio_snprintf(message, msglen, %s%s, desc, className);THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message);}}// Step 6// 步骤6设置初始化状态为being_initialized设置初始化的线程为当前线程this_oop-set_init_state(being_initialized);this_oop-set_init_thread(self);}// Step 7// 步骤7如果当前初始化的类是类而不是接口并且该类的父类还没有初始化那就在父类上递归进行完整的初始化过程。如果父类初始化过程抛出异常那么该类的初始化也要标为初始化错误状态并通知所有正在等待的线程然后抛出父类初始化抛出的异常。if (!this_oop-is_interface()) {Klass* super_klass this_oop-super();if (super_klass ! NULL super_klass-should_be_initialized()) {super_klass-initialize(THREAD); // 父类初始化过程}if (!HAS_PENDING_EXCEPTION this_oop-has_default_methods()) {this_oop-initialize_super_interfaces(this_oop, THREAD);}// If any exceptions, complete abruptly, throwing the same exception as above.if (HAS_PENDING_EXCEPTION) {Handle e(THREAD, PENDING_EXCEPTION);CLEAR_PENDING_EXCEPTION;{EXCEPTION_MARK;// Locks object, set state, and notify all waiting threadsthis_oop-set_initialization_state_and_notify(initialization_error, THREAD);CLEAR_PENDING_EXCEPTION;}DTRACE_CLASSINIT_PROBE_WAIT(super__failed, InstanceKlass::cast(this_oop()), -1,wait);THROW_OOP(e());}}// Step 8// 步骤8做一些检查工作及性能数据处理后就真正调用初始化函数进行实际初始化工作{assert(THREAD-is_Java_thread(), non-JavaThread in initialize_impl);JavaThread* jt (JavaThread*)THREAD;DTRACE_CLASSINIT_PROBE_WAIT(clinit, InstanceKlass::cast(this_oop()), -1,wait);// Timer includes any side effects of class initialization (resolution,// etc), but not recursive entry into call_class_initializer().PerfClassTraceTime timer(ClassLoader::perf_class_init_time(),ClassLoader::perf_class_init_selftime(),ClassLoader::perf_classes_inited(),jt-get_thread_stat()-perf_recursion_counts_addr(),jt-get_thread_stat()-perf_timers_addr(),PerfClassTraceTime::CLASS_CLINIT);this_oop-call_class_initializer(THREAD); // 调用类和接口的初始化函数看章节25.1.1.2}// Step 9// 步骤9初始化过程没有任务异常说明已经完成初始化设置类的状态为full_initialized并通知其他线程初始化已完成if (!HAS_PENDING_EXCEPTION) {this_oop-set_initialization_state_and_notify(fully_initialized, CHECK);{ ResourceMark rm(THREAD);debug_only(this_oop-vtable()-verify(tty, true);)}}else {// Step 10 and 11// 步骤10、11初始化过中发生异常则通过 set_initialization_state_and_notify 函数设置类的状态 initialization_error 同时通知其他线程并抛出异常Handle e(THREAD, PENDING_EXCEPTION);CLEAR_PENDING_EXCEPTION;// JVMTI has already reported the pending exception// JVMTI internal flag reset is needed in order to report ExceptionInInitializerErrorJvmtiExport::clear_detected_exception((JavaThread*)THREAD);{EXCEPTION_MARK;this_oop-set_initialization_state_and_notify(initialization_error, THREAD);CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below// JVMTI has already reported the pending exception// JVMTI internal flag reset is needed in order to report ExceptionInInitializerErrorJvmtiExport::clear_detected_exception((JavaThread*)THREAD);}DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_oop()), -1,wait);if (e-is_a(SystemDictionary::Error_klass())) {THROW_OOP(e());} else {JavaCallArguments args(e);THROW_ARG(vmSymbols::java_lang_ExceptionInInitializerError(),vmSymbols::throwable_void_signature(),args);}}DTRACE_CLASSINIT_PROBE_WAIT(end, InstanceKlass::cast(this_oop()), -1,wait);// 至此类的初始化工作完成。
}25.1.1.2 call_class_initializer
void InstanceKlass::call_class_initializer(TRAPS) {instanceKlassHandle ik (THREAD, this);call_class_initializer_impl(ik, THREAD);
}// 从_methods数组中查询出 clinit 函数并返回_methods 数组内容来源于类加载和解析这块内容会在类加载一章中讲现在只要知道有这么一个数组存放该 klass/对象 的所有方法就行。这里也简单介绍下clinit该方法是由编译器自动生成的看图25-1
Method* InstanceKlass::class_initializer() {Method* clinit find_method(vmSymbols::class_initializer_name(), vmSymbols::void_method_signature());if (clinit ! NULL clinit-has_valid_initializer_flags()) {return clinit;}return NULL;
}void InstanceKlass::call_class_initializer_impl(instanceKlassHandle this_oop, TRAPS) {if (ReplayCompiles (ReplaySuppressInitializers 1 ||ReplaySuppressInitializers 2 this_oop-class_loader() ! NULL)) {// Hide the existence of the initializer for the purpose of replaying the compilereturn;}// clinit 方法的句柄methodHandle h_method(THREAD, this_oop-class_initializer());assert(!this_oop-is_initialized(), we cannot initialize twice);if (TraceClassInitialization) {tty-print(%d Initializing , call_class_initializer_impl_counter);this_oop-name()-print_value();tty-print_cr(%s ( INTPTR_FORMAT ), h_method() NULL ? (no method) : , (address)this_oop());}if (h_method() ! NULL) {JavaCallArguments args; // No argumentsJavaValue result(T_VOID);// JavaCalls::call 表示调用java 方法这里就是调用 clinit 方法JavaCalls::call(result, h_method, args, CHECK); // Static call (no args)}
}图25-1 红色框框起来的就是编译器自动生成的方法