< prev index next >
src/share/vm/oops/instanceKlass.cpp
Print this page
*** 86,125 ****
#define HOTSPOT_CLASS_INITIALIZATION_erroneous HOTSPOT_CLASS_INITIALIZATION_ERRONEOUS
#define HOTSPOT_CLASS_INITIALIZATION_super__failed HOTSPOT_CLASS_INITIALIZATION_SUPER_FAILED
#define HOTSPOT_CLASS_INITIALIZATION_clinit HOTSPOT_CLASS_INITIALIZATION_CLINIT
#define HOTSPOT_CLASS_INITIALIZATION_error HOTSPOT_CLASS_INITIALIZATION_ERROR
#define HOTSPOT_CLASS_INITIALIZATION_end HOTSPOT_CLASS_INITIALIZATION_END
! #define DTRACE_CLASSINIT_PROBE(type, clss, thread_type) \
{ \
char* data = NULL; \
int len = 0; \
! Symbol* name = (clss)->name(); \
! if (name != NULL) { \
! data = (char*)name->bytes(); \
! len = name->utf8_length(); \
} \
HOTSPOT_CLASS_INITIALIZATION_##type( \
! data, len, (clss)->class_loader(), thread_type); \
}
! #define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \
{ \
char* data = NULL; \
int len = 0; \
! Symbol* name = (clss)->name(); \
! if (name != NULL) { \
! data = (char*)name->bytes(); \
! len = name->utf8_length(); \
} \
HOTSPOT_CLASS_INITIALIZATION_##type( \
! data, len, (clss)->class_loader(), thread_type, wait); \
}
#else // ndef DTRACE_ENABLED
! #define DTRACE_CLASSINIT_PROBE(type, clss, thread_type)
! #define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait)
#endif // ndef DTRACE_ENABLED
volatile int InstanceKlass::_total_instanceKlass_count = 0;
--- 86,125 ----
#define HOTSPOT_CLASS_INITIALIZATION_erroneous HOTSPOT_CLASS_INITIALIZATION_ERRONEOUS
#define HOTSPOT_CLASS_INITIALIZATION_super__failed HOTSPOT_CLASS_INITIALIZATION_SUPER_FAILED
#define HOTSPOT_CLASS_INITIALIZATION_clinit HOTSPOT_CLASS_INITIALIZATION_CLINIT
#define HOTSPOT_CLASS_INITIALIZATION_error HOTSPOT_CLASS_INITIALIZATION_ERROR
#define HOTSPOT_CLASS_INITIALIZATION_end HOTSPOT_CLASS_INITIALIZATION_END
! #define DTRACE_CLASSINIT_PROBE(type, thread_type) \
{ \
char* data = NULL; \
int len = 0; \
! Symbol* clss_name = name(); \
! if (clss_name != NULL) { \
! data = (char*)clss_name->bytes(); \
! len = clss_name->utf8_length(); \
} \
HOTSPOT_CLASS_INITIALIZATION_##type( \
! data, len, class_loader(), thread_type); \
}
! #define DTRACE_CLASSINIT_PROBE_WAIT(type, thread_type, wait) \
{ \
char* data = NULL; \
int len = 0; \
! Symbol* clss_name = name(); \
! if (clss_name != NULL) { \
! data = (char*)clss_name->bytes(); \
! len = clss_name->utf8_length(); \
} \
HOTSPOT_CLASS_INITIALIZATION_##type( \
! data, len, class_loader(), thread_type, wait); \
}
#else // ndef DTRACE_ENABLED
! #define DTRACE_CLASSINIT_PROBE(type, thread_type)
! #define DTRACE_CLASSINIT_PROBE_WAIT(type, thread_type, wait)
#endif // ndef DTRACE_ENABLED
volatile int InstanceKlass::_total_instanceKlass_count = 0;
*** 383,400 ****
if (this->is_not_initialized()) {
// abort if the the class has a class initializer
if (this->class_initializer() != NULL) return;
// abort if it is java.lang.Object (initialization is handled in genesis)
! Klass* super = this->super();
! if (super == NULL) return;
// abort if the super class should be initialized
! if (!InstanceKlass::cast(super)->is_initialized()) return;
// call body to expose the this pointer
! eager_initialize_impl(this);
}
}
// JVMTI spec thinks there are signers and protection domain in the
// instanceKlass. These accessors pretend these fields are there.
--- 383,400 ----
if (this->is_not_initialized()) {
// abort if the the class has a class initializer
if (this->class_initializer() != NULL) return;
// abort if it is java.lang.Object (initialization is handled in genesis)
! Klass* super_klass = super();
! if (super_klass == NULL) return;
// abort if the super class should be initialized
! if (!InstanceKlass::cast(super_klass)->is_initialized()) return;
// call body to expose the this pointer
! eager_initialize_impl();
}
}
// JVMTI spec thinks there are signers and protection domain in the
// instanceKlass. These accessors pretend these fields are there.
*** 429,492 ****
OrderAccess::storestore();
java_lang_Class::set_init_lock(java_mirror(), NULL);
assert(!is_not_initialized(), "class must be initialized now");
}
! void InstanceKlass::eager_initialize_impl(InstanceKlass* this_k) {
EXCEPTION_MARK;
HandleMark hm(THREAD);
! Handle init_lock(THREAD, this_k->init_lock());
! ObjectLocker ol(init_lock, THREAD, init_lock() != NULL);
// abort if someone beat us to the initialization
! if (!this_k->is_not_initialized()) return; // note: not equivalent to is_initialized()
! ClassState old_state = this_k->init_state();
! link_class_impl(this_k, true, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
// Abort if linking the class throws an exception.
// Use a test to avoid redundantly resetting the state if there's
// no change. Set_init_state() asserts that state changes make
// progress, whereas here we might just be spinning in place.
! if( old_state != this_k->_init_state )
! this_k->set_init_state (old_state);
} else {
// linking successfull, mark class as initialized
! this_k->set_init_state (fully_initialized);
! this_k->fence_and_clear_init_lock();
// trace
if (log_is_enabled(Info, class, init)) {
ResourceMark rm(THREAD);
! log_info(class, init)("[Initialized %s without side effects]", this_k->external_name());
}
}
}
// See "The Virtual Machine Specification" section 2.16.5 for a detailed explanation of the class initialization
// process. The step comments refers to the procedure described in that section.
// Note: implementation moved to static method to expose the this pointer.
void InstanceKlass::initialize(TRAPS) {
if (this->should_be_initialized()) {
! initialize_impl(this, CHECK);
// 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");
}
}
! bool InstanceKlass::verify_code(
! InstanceKlass* this_k, bool throw_verifyerror, TRAPS) {
// 1) Verify the bytecodes
Verifier::Mode mode =
throw_verifyerror ? Verifier::ThrowException : Verifier::NoException;
! return Verifier::verify(this_k, mode, this_k->should_verify_class(), THREAD);
}
// Used exclusively by the shared spaces dump mechanism to prevent
// classes mapped into the shared regions in new VMs from appearing linked.
--- 429,491 ----
OrderAccess::storestore();
java_lang_Class::set_init_lock(java_mirror(), NULL);
assert(!is_not_initialized(), "class must be initialized now");
}
! void InstanceKlass::eager_initialize_impl() {
EXCEPTION_MARK;
HandleMark hm(THREAD);
! Handle h_init_lock(THREAD, init_lock());
! ObjectLocker ol(h_init_lock, THREAD, init_lock() != NULL);
// abort if someone beat us to the initialization
! if (!is_not_initialized()) return; // note: not equivalent to is_initialized()
! ClassState old_state = init_state();
! link_class_impl(true, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
// Abort if linking the class throws an exception.
// Use a test to avoid redundantly resetting the state if there's
// no change. Set_init_state() asserts that state changes make
// progress, whereas here we might just be spinning in place.
! if (old_state != _init_state)
! set_init_state(old_state);
} else {
// linking successfull, mark class as initialized
! set_init_state(fully_initialized);
! fence_and_clear_init_lock();
// trace
if (log_is_enabled(Info, class, init)) {
ResourceMark rm(THREAD);
! log_info(class, init)("[Initialized %s without side effects]", external_name());
}
}
}
// See "The Virtual Machine Specification" section 2.16.5 for a detailed explanation of the class initialization
// process. The step comments refers to the procedure described in that section.
// Note: implementation moved to static method to expose the this pointer.
void InstanceKlass::initialize(TRAPS) {
if (this->should_be_initialized()) {
! initialize_impl(CHECK);
// 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");
}
}
! bool InstanceKlass::verify_code(bool throw_verifyerror, TRAPS) {
// 1) Verify the bytecodes
Verifier::Mode mode =
throw_verifyerror ? Verifier::ThrowException : Verifier::NoException;
! return Verifier::verify(this, mode, should_verify_class(), THREAD);
}
// Used exclusively by the shared spaces dump mechanism to prevent
// classes mapped into the shared regions in new VMs from appearing linked.
*** 497,573 ****
}
void InstanceKlass::link_class(TRAPS) {
assert(is_loaded(), "must be loaded");
if (!is_linked()) {
! link_class_impl(this, true, CHECK);
}
}
// Called to verify that a class can link during initialization, without
// throwing a VerifyError.
bool InstanceKlass::link_class_or_fail(TRAPS) {
assert(is_loaded(), "must be loaded");
if (!is_linked()) {
! link_class_impl(this, false, CHECK_false);
}
return is_linked();
}
! bool InstanceKlass::link_class_impl(
! InstanceKlass* this_k, bool throw_verifyerror, TRAPS) {
! if (DumpSharedSpaces && this_k->is_in_error_state()) {
// This is for CDS dumping phase only -- we use the in_error_state to indicate that
// the class has failed verification. Throwing the NoClassDefFoundError here is just
// a convenient way to stop repeat attempts to verify the same (bad) class.
//
// Note that the NoClassDefFoundError is not part of the JLS, and should not be thrown
// if we are executing Java code. This is not a problem for CDS dumping phase since
// it doesn't execute any Java code.
ResourceMark rm(THREAD);
! THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(),
! this_k->external_name(), false);
}
// return if already verified
! if (this_k->is_linked()) {
return true;
}
// Timing
// timer handles recursion
assert(THREAD->is_Java_thread(), "non-JavaThread in link_class_impl");
JavaThread* jt = (JavaThread*)THREAD;
// link super class before linking this class
! Klass* super = this_k->super();
! if (super != NULL) {
! if (super->is_interface()) { // check if super class is an interface
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(),
"class %s has interface %s as super class",
! this_k->external_name(),
! super->external_name()
);
return false;
}
! InstanceKlass* ik_super = InstanceKlass::cast(super);
! link_class_impl(ik_super, throw_verifyerror, CHECK_false);
}
// link all interfaces implemented by this class before linking this class
! Array<Klass*>* interfaces = this_k->local_interfaces();
int num_interfaces = interfaces->length();
for (int index = 0; index < num_interfaces; index++) {
InstanceKlass* interk = InstanceKlass::cast(interfaces->at(index));
! link_class_impl(interk, throw_verifyerror, CHECK_false);
}
// in case the class is linked in the process of linking its superclasses
! if (this_k->is_linked()) {
return true;
}
// trace only the link time for this klass that includes
// the verification time
--- 496,570 ----
}
void InstanceKlass::link_class(TRAPS) {
assert(is_loaded(), "must be loaded");
if (!is_linked()) {
! link_class_impl(true, CHECK);
}
}
// Called to verify that a class can link during initialization, without
// throwing a VerifyError.
bool InstanceKlass::link_class_or_fail(TRAPS) {
assert(is_loaded(), "must be loaded");
if (!is_linked()) {
! link_class_impl(false, CHECK_false);
}
return is_linked();
}
! bool InstanceKlass::link_class_impl(bool throw_verifyerror, TRAPS) {
! if (DumpSharedSpaces && is_in_error_state()) {
// This is for CDS dumping phase only -- we use the in_error_state to indicate that
// the class has failed verification. Throwing the NoClassDefFoundError here is just
// a convenient way to stop repeat attempts to verify the same (bad) class.
//
// Note that the NoClassDefFoundError is not part of the JLS, and should not be thrown
// if we are executing Java code. This is not a problem for CDS dumping phase since
// it doesn't execute any Java code.
ResourceMark rm(THREAD);
! THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(), external_name(), false);
}
// return if already verified
! if (is_linked()) {
return true;
}
// Timing
// timer handles recursion
assert(THREAD->is_Java_thread(), "non-JavaThread in link_class_impl");
JavaThread* jt = (JavaThread*)THREAD;
// link super class before linking this class
! Klass* super_klass = super();
! if (super_klass != NULL) {
! if (super_klass->is_interface()) { // check if super class is an interface
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(),
"class %s has interface %s as super class",
! external_name(),
! super_klass->external_name()
);
return false;
}
! InstanceKlass* ik_super = InstanceKlass::cast(super_klass);
! ik_super->link_class_impl(throw_verifyerror, CHECK_false);
}
// link all interfaces implemented by this class before linking this class
! Array<Klass*>* interfaces = local_interfaces();
int num_interfaces = interfaces->length();
for (int index = 0; index < num_interfaces; index++) {
InstanceKlass* interk = InstanceKlass::cast(interfaces->at(index));
! interk->link_class_impl(throw_verifyerror, CHECK_false);
}
// in case the class is linked in the process of linking its superclasses
! if (is_linked()) {
return true;
}
// trace only the link time for this klass that includes
// the verification time
*** 579,647 ****
PerfClassTraceTime::CLASS_LINK);
// verification & rewriting
{
HandleMark hm(THREAD);
! Handle init_lock(THREAD, this_k->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_k->is_linked()) {
! if (!this_k->is_rewritten()) {
{
! bool verify_ok = verify_code(this_k, 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_k->is_linked()) {
return true;
}
// also sets rewritten
! this_k->rewrite_class(CHECK_false);
! } else if (this_k->is_shared()) {
! SystemDictionaryShared::check_verification_constraints(this_k, CHECK_false);
}
// relocate jsrs and link methods after they are all rewritten
! this_k->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
//
// initialize_vtable and initialize_itable need to be rerun for
// a shared class if the class is not loaded by the NULL classloader.
! ClassLoaderData * loader_data = this_k->class_loader_data();
! if (!(this_k->is_shared() &&
loader_data->is_the_null_class_loader_data())) {
ResourceMark rm(THREAD);
! this_k->vtable()->initialize_vtable(true, CHECK_false);
! this_k->itable()->initialize_itable(true, CHECK_false);
}
#ifdef ASSERT
else {
ResourceMark rm(THREAD);
! this_k->vtable()->verify(tty, true);
// In case itable verification is ever added.
! // this_k->itable()->verify(tty, true);
}
#endif
! this_k->set_init_state(linked);
if (JvmtiExport::should_post_class_prepare()) {
Thread *thread = THREAD;
assert(thread->is_Java_thread(), "thread->is_Java_thread()");
! JvmtiExport::post_class_prepare((JavaThread *) thread, this_k);
}
}
}
return true;
}
--- 576,644 ----
PerfClassTraceTime::CLASS_LINK);
// verification & rewriting
{
HandleMark hm(THREAD);
! Handle h_init_lock(THREAD, init_lock());
! ObjectLocker ol(h_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 (!is_linked()) {
! if (!is_rewritten()) {
{
! bool verify_ok = verify_code(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 (is_linked()) {
return true;
}
// also sets rewritten
! rewrite_class(CHECK_false);
! } else if (is_shared()) {
! SystemDictionaryShared::check_verification_constraints(this, CHECK_false);
}
// relocate jsrs and link methods after they are all rewritten
! 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
//
// initialize_vtable and initialize_itable need to be rerun for
// a shared class if the class is not loaded by the NULL classloader.
! ClassLoaderData * loader_data = class_loader_data();
! if (!(is_shared() &&
loader_data->is_the_null_class_loader_data())) {
ResourceMark rm(THREAD);
! vtable()->initialize_vtable(true, CHECK_false);
! itable()->initialize_itable(true, CHECK_false);
}
#ifdef ASSERT
else {
ResourceMark rm(THREAD);
! vtable()->verify(tty, true);
// In case itable verification is ever added.
! // itable()->verify(tty, true);
}
#endif
! set_init_state(linked);
if (JvmtiExport::should_post_class_prepare()) {
Thread *thread = THREAD;
assert(thread->is_Java_thread(), "thread->is_Java_thread()");
! JvmtiExport::post_class_prepare((JavaThread *) thread, this);
}
}
}
return true;
}
*** 672,747 ****
m->link_method(m, CHECK);
}
}
// Eagerly initialize superinterfaces that declare default methods (concrete instance: any access)
! void InstanceKlass::initialize_super_interfaces(InstanceKlass* this_k, TRAPS) {
! assert (this_k->has_nonstatic_concrete_methods(), "caller should have checked this");
! for (int i = 0; i < this_k->local_interfaces()->length(); ++i) {
! Klass* iface = this_k->local_interfaces()->at(i);
InstanceKlass* ik = InstanceKlass::cast(iface);
// Initialization is depth first search ie. we start with top of the inheritance tree
// has_nonstatic_concrete_methods drives searching superinterfaces since it
// means has_nonstatic_concrete_methods in its superinterface hierarchy
if (ik->has_nonstatic_concrete_methods()) {
! ik->initialize_super_interfaces(ik, CHECK);
}
// Only initialize() interfaces that "declare" concrete methods.
if (ik->should_be_initialized() && ik->declares_nonstatic_concrete_methods()) {
ik->initialize(CHECK);
}
}
}
! void InstanceKlass::initialize_impl(InstanceKlass* this_k, TRAPS) {
HandleMark hm(THREAD);
// Make sure klass is linked (verified) before initialization
// A class could already be verified, since it has been reflected upon.
! this_k->link_class(CHECK);
! DTRACE_CLASSINIT_PROBE(required, this_k, -1);
bool wait = false;
// refer to the JVM book page 47 for description of steps
// Step 1
{
! Handle init_lock(THREAD, this_k->init_lock());
! ObjectLocker ol(init_lock, THREAD, init_lock() != NULL);
Thread *self = THREAD; // it's passed the current thread
// Step 2
// If we were to use wait() instead of waitInterruptibly() then
// we might end up throwing IE from link/symbol resolution sites
// that aren't expected to throw. This would wreak havoc. See 6320309.
! while(this_k->is_being_initialized() && !this_k->is_reentrant_initialization(self)) {
wait = true;
ol.waitUninterruptibly(CHECK);
}
// Step 3
! if (this_k->is_being_initialized() && this_k->is_reentrant_initialization(self)) {
! DTRACE_CLASSINIT_PROBE_WAIT(recursive, this_k, -1,wait);
return;
}
// Step 4
! if (this_k->is_initialized()) {
! DTRACE_CLASSINIT_PROBE_WAIT(concurrent, this_k, -1,wait);
return;
}
// Step 5
! if (this_k->is_in_error_state()) {
! DTRACE_CLASSINIT_PROBE_WAIT(erroneous, this_k, -1,wait);
ResourceMark rm(THREAD);
const char* desc = "Could not initialize class ";
! const char* className = this_k->external_name();
size_t msglen = strlen(desc) + strlen(className) + 1;
char* message = NEW_RESOURCE_ARRAY(char, msglen);
if (NULL == message) {
// Out of memory: can't create detailed error message
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className);
--- 669,744 ----
m->link_method(m, CHECK);
}
}
// Eagerly initialize superinterfaces that declare default methods (concrete instance: any access)
! void InstanceKlass::initialize_super_interfaces(TRAPS) {
! assert (has_nonstatic_concrete_methods(), "caller should have checked this");
! for (int i = 0; i < local_interfaces()->length(); ++i) {
! Klass* iface = local_interfaces()->at(i);
InstanceKlass* ik = InstanceKlass::cast(iface);
// Initialization is depth first search ie. we start with top of the inheritance tree
// has_nonstatic_concrete_methods drives searching superinterfaces since it
// means has_nonstatic_concrete_methods in its superinterface hierarchy
if (ik->has_nonstatic_concrete_methods()) {
! ik->initialize_super_interfaces(CHECK);
}
// Only initialize() interfaces that "declare" concrete methods.
if (ik->should_be_initialized() && ik->declares_nonstatic_concrete_methods()) {
ik->initialize(CHECK);
}
}
}
! void InstanceKlass::initialize_impl(TRAPS) {
HandleMark hm(THREAD);
// Make sure klass is linked (verified) before initialization
// A class could already be verified, since it has been reflected upon.
! link_class(CHECK);
! DTRACE_CLASSINIT_PROBE(required, -1);
bool wait = false;
// refer to the JVM book page 47 for description of steps
// Step 1
{
! Handle h_init_lock(THREAD, init_lock());
! ObjectLocker ol(h_init_lock, THREAD, init_lock() != NULL);
Thread *self = THREAD; // it's passed the current thread
// Step 2
// If we were to use wait() instead of waitInterruptibly() then
// we might end up throwing IE from link/symbol resolution sites
// that aren't expected to throw. This would wreak havoc. See 6320309.
! while(is_being_initialized() && !is_reentrant_initialization(self)) {
wait = true;
ol.waitUninterruptibly(CHECK);
}
// Step 3
! if (is_being_initialized() && is_reentrant_initialization(self)) {
! DTRACE_CLASSINIT_PROBE_WAIT(recursive, -1, wait);
return;
}
// Step 4
! if (is_initialized()) {
! DTRACE_CLASSINIT_PROBE_WAIT(concurrent, -1, wait);
return;
}
// Step 5
! if (is_in_error_state()) {
! DTRACE_CLASSINIT_PROBE_WAIT(erroneous, -1, wait);
ResourceMark rm(THREAD);
const char* desc = "Could not initialize class ";
! const char* className = external_name();
size_t msglen = strlen(desc) + strlen(className) + 1;
char* message = NEW_RESOURCE_ARRAY(char, msglen);
if (NULL == message) {
// Out of memory: can't create detailed error message
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className);
*** 750,819 ****
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message);
}
}
// Step 6
! this_k->set_init_state(being_initialized);
! this_k->set_init_thread(self);
}
// Step 7
// Next, if C is a class rather than an interface, initialize it's super class and super
// interfaces.
! if (!this_k->is_interface()) {
! Klass* super_klass = this_k->super();
if (super_klass != NULL && super_klass->should_be_initialized()) {
super_klass->initialize(THREAD);
}
// If C implements any interface that declares a non-static, concrete method,
// the initialization of C triggers initialization of its super interfaces.
// Only need to recurse if has_nonstatic_concrete_methods which includes declaring and
// having a superinterface that declares, non-static, concrete methods
! if (!HAS_PENDING_EXCEPTION && this_k->has_nonstatic_concrete_methods()) {
! this_k->initialize_super_interfaces(this_k, 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 threads
! this_k->set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION;
}
! DTRACE_CLASSINIT_PROBE_WAIT(super__failed, this_k, -1,wait);
THROW_OOP(e());
}
}
// Look for aot compiled methods for this klass, including class initializer.
! AOTLoader::load_for_klass(this_k, THREAD);
// Step 8
{
assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl");
JavaThread* jt = (JavaThread*)THREAD;
! DTRACE_CLASSINIT_PROBE_WAIT(clinit, this_k, -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_k->call_class_initializer(THREAD);
}
// Step 9
if (!HAS_PENDING_EXCEPTION) {
! this_k->set_initialization_state_and_notify(fully_initialized, CHECK);
{ ResourceMark rm(THREAD);
! debug_only(this_k->vtable()->verify(tty, true);)
}
}
else {
// Step 10 and 11
Handle e(THREAD, PENDING_EXCEPTION);
--- 747,816 ----
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message);
}
}
// Step 6
! set_init_state(being_initialized);
! set_init_thread(self);
}
// Step 7
// Next, if C is a class rather than an interface, initialize it's super class and super
// interfaces.
! if (!is_interface()) {
! Klass* super_klass = super();
if (super_klass != NULL && super_klass->should_be_initialized()) {
super_klass->initialize(THREAD);
}
// If C implements any interface that declares a non-static, concrete method,
// the initialization of C triggers initialization of its super interfaces.
// Only need to recurse if has_nonstatic_concrete_methods which includes declaring and
// having a superinterface that declares, non-static, concrete methods
! if (!HAS_PENDING_EXCEPTION && has_nonstatic_concrete_methods()) {
! initialize_super_interfaces(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 threads
! set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION;
}
! DTRACE_CLASSINIT_PROBE_WAIT(super__failed, -1, wait);
THROW_OOP(e());
}
}
// Look for aot compiled methods for this klass, including class initializer.
! AOTLoader::load_for_klass(this, THREAD);
// Step 8
{
assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl");
JavaThread* jt = (JavaThread*)THREAD;
! DTRACE_CLASSINIT_PROBE_WAIT(clinit, -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);
! call_class_initializer(THREAD);
}
// Step 9
if (!HAS_PENDING_EXCEPTION) {
! set_initialization_state_and_notify(fully_initialized, CHECK);
{ ResourceMark rm(THREAD);
! debug_only(vtable()->verify(tty, true);)
}
}
else {
// Step 10 and 11
Handle e(THREAD, PENDING_EXCEPTION);
*** 821,865 ****
// JVMTI has already reported the pending exception
// JVMTI internal flag reset is needed in order to report ExceptionInInitializerError
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
{
EXCEPTION_MARK;
! this_k->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 ExceptionInInitializerError
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
}
! DTRACE_CLASSINIT_PROBE_WAIT(error, this_k, -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, this_k, -1,wait);
}
// Note: implementation moved to static method to expose the this pointer.
void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS) {
! set_initialization_state_and_notify_impl(this, state, CHECK);
}
! void InstanceKlass::set_initialization_state_and_notify_impl(InstanceKlass* this_k, ClassState state, TRAPS) {
! Handle init_lock(THREAD, this_k->init_lock());
if (init_lock() != NULL) {
! ObjectLocker ol(init_lock, THREAD);
! this_k->set_init_state(state);
! this_k->fence_and_clear_init_lock();
ol.notify_all(CHECK);
} else {
assert(init_lock() != NULL, "The initialization state should never be set twice");
! this_k->set_init_state(state);
}
}
// The embedded _implementor field can only record one implementor.
// When there are more than one implementors, the _implementor field
--- 818,862 ----
// JVMTI has already reported the pending exception
// JVMTI internal flag reset is needed in order to report ExceptionInInitializerError
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
{
EXCEPTION_MARK;
! 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 ExceptionInInitializerError
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
}
! DTRACE_CLASSINIT_PROBE_WAIT(error, -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, -1, wait);
}
// Note: implementation moved to static method to expose the this pointer.
void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS) {
! set_initialization_state_and_notify_impl(state, CHECK);
}
! void InstanceKlass::set_initialization_state_and_notify_impl(ClassState state, TRAPS) {
! Handle h_init_lock(THREAD, init_lock());
if (init_lock() != NULL) {
! ObjectLocker ol(h_init_lock, THREAD);
! set_init_state(state);
! fence_and_clear_init_lock();
ol.notify_all(CHECK);
} else {
assert(init_lock() != NULL, "The initialization state should never be set twice");
! set_init_state(state);
}
}
// The embedded _implementor field can only record one implementor.
// When there are more than one implementors, the _implementor field
*** 1035,1069 ****
: vmSymbols::java_lang_IllegalAccessException(), external_name());
}
}
Klass* InstanceKlass::array_klass_impl(bool or_null, int n, TRAPS) {
- return array_klass_impl(this, or_null, n, THREAD);
- }
-
- Klass* InstanceKlass::array_klass_impl(InstanceKlass* this_k, bool or_null, int n, TRAPS) {
// Need load-acquire for lock-free read
! if (this_k->array_klasses_acquire() == NULL) {
if (or_null) return NULL;
ResourceMark rm;
JavaThread *jt = (JavaThread *)THREAD;
{
// Atomic creation of array_klasses
MutexLocker mc(Compile_lock, THREAD); // for vtables
MutexLocker ma(MultiArray_lock, THREAD);
// Check if update has already taken place
! if (this_k->array_klasses() == NULL) {
! Klass* k = ObjArrayKlass::allocate_objArray_klass(this_k->class_loader_data(), 1, this_k, CHECK_NULL);
// use 'release' to pair with lock-free load
! this_k->release_set_array_klasses(k);
}
}
}
// _this will always be set at this point
! ObjArrayKlass* oak = (ObjArrayKlass*)this_k->array_klasses();
if (or_null) {
return oak->array_klass_or_null(n);
}
return oak->array_klass(n, THREAD);
}
--- 1032,1062 ----
: vmSymbols::java_lang_IllegalAccessException(), external_name());
}
}
Klass* InstanceKlass::array_klass_impl(bool or_null, int n, TRAPS) {
// Need load-acquire for lock-free read
! if (array_klasses_acquire() == NULL) {
if (or_null) return NULL;
ResourceMark rm;
JavaThread *jt = (JavaThread *)THREAD;
{
// Atomic creation of array_klasses
MutexLocker mc(Compile_lock, THREAD); // for vtables
MutexLocker ma(MultiArray_lock, THREAD);
// Check if update has already taken place
! if (array_klasses() == NULL) {
! Klass* k = ObjArrayKlass::allocate_objArray_klass(class_loader_data(), 1, this, CHECK_NULL);
// use 'release' to pair with lock-free load
! release_set_array_klasses(k);
}
}
}
// _this will always be set at this point
! ObjArrayKlass* oak = (ObjArrayKlass*)array_klasses();
if (or_null) {
return oak->array_klass_or_null(n);
}
return oak->array_klass(n, THREAD);
}
*** 1071,1081 ****
Klass* InstanceKlass::array_klass_impl(bool or_null, TRAPS) {
return array_klass_impl(or_null, 1, THREAD);
}
void InstanceKlass::call_class_initializer(TRAPS) {
! call_class_initializer_impl(this, THREAD);
}
static int call_class_initializer_impl_counter = 0; // for debugging
Method* InstanceKlass::class_initializer() const {
--- 1064,1074 ----
Klass* InstanceKlass::array_klass_impl(bool or_null, TRAPS) {
return array_klass_impl(or_null, 1, THREAD);
}
void InstanceKlass::call_class_initializer(TRAPS) {
! call_class_initializer_impl(THREAD);
}
static int call_class_initializer_impl_counter = 0; // for debugging
Method* InstanceKlass::class_initializer() const {
*** 1085,1110 ****
return clinit;
}
return NULL;
}
! void InstanceKlass::call_class_initializer_impl(InstanceKlass* this_k, TRAPS) {
if (ReplayCompiles &&
(ReplaySuppressInitializers == 1 ||
! ReplaySuppressInitializers >= 2 && this_k->class_loader() != NULL)) {
// Hide the existence of the initializer for the purpose of replaying the compile
return;
}
! methodHandle h_method(THREAD, this_k->class_initializer());
! assert(!this_k->is_initialized(), "we cannot initialize twice");
if (log_is_enabled(Info, class, init)) {
ResourceMark rm;
outputStream* log = Log(class, init)::info_stream();
log->print("%d Initializing ", call_class_initializer_impl_counter++);
! this_k->name()->print_value_on(log);
! log->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", p2i(this_k));
}
if (h_method() != NULL) {
JavaCallArguments args; // No arguments
JavaValue result(T_VOID);
JavaCalls::call(&result, h_method, &args, CHECK); // Static call (no args)
--- 1078,1103 ----
return clinit;
}
return NULL;
}
! void InstanceKlass::call_class_initializer_impl(TRAPS) {
if (ReplayCompiles &&
(ReplaySuppressInitializers == 1 ||
! ReplaySuppressInitializers >= 2 && class_loader() != NULL)) {
// Hide the existence of the initializer for the purpose of replaying the compile
return;
}
! methodHandle h_method(THREAD, class_initializer());
! assert(!is_initialized(), "we cannot initialize twice");
if (log_is_enabled(Info, class, init)) {
ResourceMark rm;
outputStream* log = Log(class, init)::info_stream();
log->print("%d Initializing ", call_class_initializer_impl_counter++);
! name()->print_value_on(log);
! log->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", p2i(this));
}
if (h_method() != NULL) {
JavaCallArguments args; // No arguments
JavaValue result(T_VOID);
JavaCalls::call(&result, h_method, &args, CHECK); // Static call (no args)
*** 1251,1267 ****
}
}
void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle mirror, TRAPS) {
! do_local_static_fields_impl(this, f, mirror, CHECK);
}
! void InstanceKlass::do_local_static_fields_impl(InstanceKlass* this_k,
! void f(fieldDescriptor* fd, Handle, TRAPS), Handle mirror, TRAPS) {
! for (JavaFieldStream fs(this_k); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) {
fieldDescriptor& fd = fs.field_descriptor();
f(&fd, mirror, CHECK);
}
}
--- 1244,1260 ----
}
}
void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle mirror, TRAPS) {
! do_local_static_fields_impl(f, mirror, CHECK);
}
! void InstanceKlass::do_local_static_fields_impl(void f(fieldDescriptor* fd, Handle, TRAPS),
! Handle mirror, TRAPS) {
! for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) {
fieldDescriptor& fd = fs.field_descriptor();
f(&fd, mirror, CHECK);
}
}
*** 1616,1643 ****
}
return NULL;
}
/* jni_id_for_impl for jfieldIds only */
! JNIid* InstanceKlass::jni_id_for_impl(InstanceKlass* this_k, int offset) {
MutexLocker ml(JfieldIdCreation_lock);
// Retry lookup after we got the lock
! JNIid* probe = this_k->jni_ids() == NULL ? NULL : this_k->jni_ids()->find(offset);
if (probe == NULL) {
// Slow case, allocate new static field identifier
! probe = new JNIid(this_k, offset, this_k->jni_ids());
! this_k->set_jni_ids(probe);
}
return probe;
}
/* jni_id_for for jfieldIds only */
JNIid* InstanceKlass::jni_id_for(int offset) {
JNIid* probe = jni_ids() == NULL ? NULL : jni_ids()->find(offset);
if (probe == NULL) {
! probe = jni_id_for_impl(this, offset);
}
return probe;
}
u2 InstanceKlass::enclosing_method_data(int offset) const {
--- 1609,1636 ----
}
return NULL;
}
/* jni_id_for_impl for jfieldIds only */
! JNIid* InstanceKlass::jni_id_for_impl(int offset) {
MutexLocker ml(JfieldIdCreation_lock);
// Retry lookup after we got the lock
! JNIid* probe = jni_ids() == NULL ? NULL : jni_ids()->find(offset);
if (probe == NULL) {
// Slow case, allocate new static field identifier
! probe = new JNIid(this, offset, jni_ids());
! set_jni_ids(probe);
}
return probe;
}
/* jni_id_for for jfieldIds only */
JNIid* InstanceKlass::jni_id_for(int offset) {
JNIid* probe = jni_ids() == NULL ? NULL : jni_ids()->find(offset);
if (probe == NULL) {
! probe = jni_id_for_impl(offset);
}
return probe;
}
u2 InstanceKlass::enclosing_method_data(int offset) const {
< prev index next >