diff options
Diffstat (limited to 'src/share/vm/oops/instanceKlass.cpp')
-rw-r--r-- | src/share/vm/oops/instanceKlass.cpp | 144 |
1 files changed, 118 insertions, 26 deletions
diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp index d4f497ed3..c6a5bddb0 100644 --- a/src/share/vm/oops/instanceKlass.cpp +++ b/src/share/vm/oops/instanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,7 @@ #include "prims/jvmtiExport.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" #include "prims/jvmtiRedefineClasses.hpp" +#include "prims/jvmtiThreadState.hpp" #include "prims/methodComparator.hpp" #include "runtime/fieldDescriptor.hpp" #include "runtime/handles.inline.hpp" @@ -110,7 +111,7 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end, len = name->utf8_length(); \ } \ HS_DTRACE_PROBE4(hotspot, class__initialization__##type, \ - data, len, SOLARIS_ONLY((void *))(clss)->class_loader(), thread_type); \ + data, len, (void *)(clss)->class_loader(), thread_type); \ } #define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \ @@ -123,7 +124,7 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end, len = name->utf8_length(); \ } \ HS_DTRACE_PROBE5(hotspot, class__initialization__##type, \ - data, len, SOLARIS_ONLY((void *))(clss)->class_loader(), thread_type, wait); \ + data, len, (void *)(clss)->class_loader(), thread_type, wait); \ } #else /* USDT2 */ @@ -438,6 +439,9 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { if (!constants()->is_shared()) { MetadataFactory::free_metadata(loader_data, constants()); } + // Delete any cached resolution errors for the constant pool + SystemDictionary::delete_resolution_error(constants()); + set_constants(NULL); } @@ -928,10 +932,16 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) { // Step 10 and 11 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 ExceptionInInitializerError + JvmtiExport::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 ExceptionInInitializerError + JvmtiExport::clear_detected_exception((JavaThread*)THREAD); } DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_oop()), -1,wait); if (e->is_a(SystemDictionary::Error_klass())) { @@ -1562,6 +1572,21 @@ Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, M return NULL; } +#ifdef ASSERT +// search through class hierarchy and return true if this class or +// one of the superclasses was redefined +bool InstanceKlass::has_redefined_this_or_super() const { + const InstanceKlass* klass = this; + while (klass != NULL) { + if (klass->has_been_redefined()) { + return true; + } + klass = InstanceKlass::cast(klass->super()); + } + return false; +} +#endif + // lookup a method in the default methods list then in all transitive interfaces // Do NOT return private or static methods Method* InstanceKlass::lookup_method_in_ordered_interfaces(Symbol* name, @@ -1944,7 +1969,7 @@ void InstanceKlass::add_dependent_nmethod(nmethod* nm) { // find a corresponding bucket otherwise there's a bug in the // recording of dependecies. // -void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { +void InstanceKlass::remove_dependent_nmethod(nmethod* nm, bool delete_immediately) { assert_locked_or_safepoint(CodeCache_lock); nmethodBucket* b = _dependencies; nmethodBucket* last = NULL; @@ -1953,7 +1978,17 @@ void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { int val = b->decrement(); guarantee(val >= 0, err_msg("Underflow: %d", val)); if (val == 0) { - set_has_unloaded_dependent(true); + if (delete_immediately) { + if (last == NULL) { + _dependencies = b->next(); + } else { + last->set_next(b->next()); + } + delete b; + } else { + // The deletion of this entry is deferred until a later, potentially parallel GC phase. + set_has_unloaded_dependent(true); + } } return; } @@ -2293,6 +2328,13 @@ int InstanceKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { #endif // INCLUDE_ALL_GCS +void InstanceKlass::clean_weak_instanceklass_links(BoolObjectClosure* is_alive) { + clean_implementors_list(is_alive); + clean_method_data(is_alive); + + clean_dependent_nmethods(); +} + void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { assert(class_loader_data()->is_alive(is_alive), "this klass should be live"); if (is_interface()) { @@ -2798,30 +2840,33 @@ Method* InstanceKlass::method_at_itable(Klass* holder, int index, TRAPS) { // not yet in the vtable due to concurrent subclass define and superinterface // redefinition // Note: those in the vtable, should have been updated via adjust_method_entries -void InstanceKlass::adjust_default_methods(Method** old_methods, Method** new_methods, - int methods_length, bool* trace_name_printed) { +void InstanceKlass::adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed) { // search the default_methods for uses of either obsolete or EMCP methods if (default_methods() != NULL) { - for (int j = 0; j < methods_length; j++) { - Method* old_method = old_methods[j]; - Method* new_method = new_methods[j]; - - for (int index = 0; index < default_methods()->length(); index ++) { - if (default_methods()->at(index) == old_method) { - default_methods()->at_put(index, new_method); - if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { - if (!(*trace_name_printed)) { - // RC_TRACE_MESG macro has an embedded ResourceMark - RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s", - external_name(), - old_method->method_holder()->external_name())); - *trace_name_printed = true; - } - RC_TRACE(0x00100000, ("default method update: %s(%s) ", - new_method->name()->as_C_string(), - new_method->signature()->as_C_string())); - } + for (int index = 0; index < default_methods()->length(); index ++) { + Method* old_method = default_methods()->at(index); + if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) { + continue; // skip uninteresting entries + } + assert(!old_method->is_deleted(), "default methods may not be deleted"); + + Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum()); + + assert(new_method != NULL, "method_with_idnum() should not be NULL"); + assert(old_method != new_method, "sanity check"); + + default_methods()->at_put(index, new_method); + if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { + if (!(*trace_name_printed)) { + // RC_TRACE_MESG macro has an embedded ResourceMark + RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s", + external_name(), + old_method->method_holder()->external_name())); + *trace_name_printed = true; } + RC_TRACE(0x00100000, ("default method update: %s(%s) ", + new_method->name()->as_C_string(), + new_method->signature()->as_C_string())); } } } @@ -3744,6 +3789,22 @@ bool InstanceKlass::has_previous_version() const { } // end has_previous_version() +InstanceKlass* InstanceKlass::get_klass_version(int version) { + if (constants()->version() == version) { + return this; + } + PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this); + for (PreviousVersionNode * pv_node = pvw.next_previous_version(); + pv_node != NULL; pv_node = pvw.next_previous_version()) { + ConstantPool* prev_cp = pv_node->prev_constant_pool(); + if (prev_cp->version() == version) { + return prev_cp->pool_holder(); + } + } + return NULL; // None found +} + + Method* InstanceKlass::method_with_idnum(int idnum) { Method* m = NULL; if (idnum < methods()->length()) { @@ -3762,6 +3823,37 @@ Method* InstanceKlass::method_with_idnum(int idnum) { return m; } + +Method* InstanceKlass::method_with_orig_idnum(int idnum) { + if (idnum >= methods()->length()) { + return NULL; + } + Method* m = methods()->at(idnum); + if (m != NULL && m->orig_method_idnum() == idnum) { + return m; + } + // Obsolete method idnum does not match the original idnum + for (int index = 0; index < methods()->length(); ++index) { + m = methods()->at(index); + if (m->orig_method_idnum() == idnum) { + return m; + } + } + // None found, return null for the caller to handle. + return NULL; +} + + +Method* InstanceKlass::method_with_orig_idnum(int idnum, int version) { + InstanceKlass* holder = get_klass_version(version); + if (holder == NULL) { + return NULL; // The version of klass is gone, no method is found + } + Method* method = holder->method_with_orig_idnum(idnum); + return method; +} + + jint InstanceKlass::get_cached_class_file_len() { return VM_RedefineClasses::get_cached_class_file_len(_cached_class_file); } |