aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/oops/instanceKlass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/share/vm/oops/instanceKlass.cpp')
-rw-r--r--src/share/vm/oops/instanceKlass.cpp144
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);
}