src/share/vm/classfile/javaClasses.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File 8140685.01 Cdiff src/share/vm/classfile/javaClasses.cpp

src/share/vm/classfile/javaClasses.cpp

Print this page

        

*** 22,31 **** --- 22,32 ---- * */ #include "precompiled.hpp" #include "classfile/altHashing.hpp" + #include "classfile/backtrace.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/stringTable.hpp" #include "classfile/vmSymbols.hpp" #include "code/debugInfo.hpp" #include "code/pcDesc.hpp"
*** 1328,1343 **** } static inline int version_at(unsigned int merged) { return extract_low_short_from_int(merged); } ! static inline bool version_matches(Method* method, int version) { ! assert(version < MAX_VERSION, "version is too big"); ! return method != NULL && (method->constants()->version() == version); ! } ! ! static inline int get_line_number(Method* method, int bci) { int line_number = 0; if (method->is_native()) { // Negative value different from -1 below, enabling Java code in // class java.lang.StackTraceElement to distinguish "native" from // "no LineNumberTable". JDK tests for -2. --- 1329,1339 ---- } static inline int version_at(unsigned int merged) { return extract_low_short_from_int(merged); } ! static inline int get_line_number(const methodHandle& method, int bci) { int line_number = 0; if (method->is_native()) { // Negative value different from -1 below, enabling Java code in // class java.lang.StackTraceElement to distinguish "native" from // "no LineNumberTable". JDK tests for -2.
*** 1350,1380 **** } } return line_number; } // This class provides a simple wrapper over the internal structure of // exception backtrace to insulate users of the backtrace from needing // to know what it looks like. class BacktraceBuilder: public StackObj { private: Handle _backtrace; objArrayOop _head; typeArrayOop _methods; typeArrayOop _bcis; objArrayOop _mirrors; - typeArrayOop _cprefs; // needed to insulate method name against redefinition int _index; No_Safepoint_Verifier _nsv; public: enum { trace_methods_offset = java_lang_Throwable::trace_methods_offset, trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, - trace_cprefs_offset = java_lang_Throwable::trace_cprefs_offset, trace_next_offset = java_lang_Throwable::trace_next_offset, trace_size = java_lang_Throwable::trace_size, trace_chunk_size = java_lang_Throwable::trace_chunk_size }; --- 1346,1432 ---- } } return line_number; } + // Mark all of the methods in this backtrace as on the stack during full GC + // so that they aren't deallocated if any of these methods are redefined. + void java_lang_Throwable::mark_on_stack(oop throwable) { + objArrayOop result = objArrayOop(backtrace(throwable)); + + while (result != NULL) { + typeArrayOop methods = typeArrayOop(result->obj_at(trace_methods_offset)); + + if (methods == NULL) { + return; + } + + int length = methods->length(); + for (int index = 0; index < length; index++) { + Method* method = ((Method*)methods->metadata_at(index)); + if (method == NULL) return; + method->set_on_stack(true); + } + result = objArrayOop(result->obj_at(trace_next_offset)); + } + } + // This class provides a simple wrapper over the internal structure of // exception backtrace to insulate users of the backtrace from needing // to know what it looks like. class BacktraceBuilder: public StackObj { private: Handle _backtrace; objArrayOop _head; typeArrayOop _methods; typeArrayOop _bcis; objArrayOop _mirrors; int _index; No_Safepoint_Verifier _nsv; + void add_backtrace(Handle throwable) { + Pause_No_Safepoint_Verifier pnsv(&_nsv); + // RedefineClasses support + // Save this backtrace object to find methods used in Java heap + BacktraceList::add(throwable()); + } + + void expand(TRAPS) { + objArrayHandle old_head(THREAD, _head); + Pause_No_Safepoint_Verifier pnsv(&_nsv); + + objArrayOop head = oopFactory::new_objectArray(trace_size, CHECK); + objArrayHandle new_head(THREAD, head); + + typeArrayOop methods = oopFactory::new_metadataArray(trace_chunk_size, CHECK); + typeArrayHandle new_methods(THREAD, methods); + + typeArrayOop bcis = oopFactory::new_intArray(trace_chunk_size, CHECK); + typeArrayHandle new_bcis(THREAD, bcis); + + objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); + objArrayHandle new_mirrors(THREAD, mirrors); + + if (!old_head.is_null()) { + old_head->obj_at_put(trace_next_offset, new_head()); + } + new_head->obj_at_put(trace_methods_offset, new_methods()); + new_head->obj_at_put(trace_bcis_offset, new_bcis()); + new_head->obj_at_put(trace_mirrors_offset, new_mirrors()); + + _head = new_head(); + _methods = new_methods(); + _bcis = new_bcis(); + _mirrors = new_mirrors(); + _index = 0; + } public: enum { trace_methods_offset = java_lang_Throwable::trace_methods_offset, trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, trace_next_offset = java_lang_Throwable::trace_next_offset, trace_size = java_lang_Throwable::trace_size, trace_chunk_size = java_lang_Throwable::trace_chunk_size };
*** 1392,1463 **** static objArrayOop get_mirrors(objArrayHandle chunk) { objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); assert(mirrors != NULL, "mirror array should be initialized in backtrace"); return mirrors; } - static typeArrayOop get_cprefs(objArrayHandle chunk) { - typeArrayOop cprefs = typeArrayOop(chunk->obj_at(trace_cprefs_offset)); - assert(cprefs != NULL, "cprefs array should be initialized in backtrace"); - return cprefs; - } // constructor for new backtrace ! BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _cprefs(NULL) { expand(CHECK); _backtrace = _head; _index = 0; } BacktraceBuilder(objArrayHandle backtrace) { _methods = get_methods(backtrace); _bcis = get_bcis(backtrace); _mirrors = get_mirrors(backtrace); - _cprefs = get_cprefs(backtrace); assert(_methods->length() == _bcis->length() && _methods->length() == _mirrors->length(), "method and source information arrays should match"); // head is the preallocated backtrace _backtrace = _head = backtrace(); _index = 0; } - void expand(TRAPS) { - objArrayHandle old_head(THREAD, _head); - Pause_No_Safepoint_Verifier pnsv(&_nsv); - - objArrayOop head = oopFactory::new_objectArray(trace_size, CHECK); - objArrayHandle new_head(THREAD, head); - - typeArrayOop methods = oopFactory::new_shortArray(trace_chunk_size, CHECK); - typeArrayHandle new_methods(THREAD, methods); - - typeArrayOop bcis = oopFactory::new_intArray(trace_chunk_size, CHECK); - typeArrayHandle new_bcis(THREAD, bcis); - - objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); - objArrayHandle new_mirrors(THREAD, mirrors); - - typeArrayOop cprefs = oopFactory::new_shortArray(trace_chunk_size, CHECK); - typeArrayHandle new_cprefs(THREAD, cprefs); - - if (!old_head.is_null()) { - old_head->obj_at_put(trace_next_offset, new_head()); - } - new_head->obj_at_put(trace_methods_offset, new_methods()); - new_head->obj_at_put(trace_bcis_offset, new_bcis()); - new_head->obj_at_put(trace_mirrors_offset, new_mirrors()); - new_head->obj_at_put(trace_cprefs_offset, new_cprefs()); - - _head = new_head(); - _methods = new_methods(); - _bcis = new_bcis(); - _mirrors = new_mirrors(); - _cprefs = new_cprefs(); - _index = 0; - } - oop backtrace() { return _backtrace(); } inline void push(Method* method, int bci, TRAPS) { --- 1444,1475 ---- static objArrayOop get_mirrors(objArrayHandle chunk) { objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); assert(mirrors != NULL, "mirror array should be initialized in backtrace"); return mirrors; } // constructor for new backtrace ! BacktraceBuilder(Handle throwable, TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL) { expand(CHECK); _backtrace = _head; _index = 0; + add_backtrace(throwable); } BacktraceBuilder(objArrayHandle backtrace) { _methods = get_methods(backtrace); _bcis = get_bcis(backtrace); _mirrors = get_mirrors(backtrace); assert(_methods->length() == _bcis->length() && _methods->length() == _mirrors->length(), "method and source information arrays should match"); // head is the preallocated backtrace _backtrace = _head = backtrace(); _index = 0; } oop backtrace() { return _backtrace(); } inline void push(Method* method, int bci, TRAPS) {
*** 1470,1482 **** methodHandle mhandle(THREAD, method); expand(CHECK); method = mhandle(); } ! _methods->short_at_put(_index, method->orig_method_idnum()); _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version())); - _cprefs->short_at_put(_index, method->name_index()); // We need to save the mirrors in the backtrace to keep the class // from being unloaded while we still have this stack trace. assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror"); _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); --- 1482,1493 ---- methodHandle mhandle(THREAD, method); expand(CHECK); method = mhandle(); } ! _methods->metadata_at_put(_index, method); _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version())); // We need to save the mirrors in the backtrace to keep the class // from being unloaded while we still have this stack trace. assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror"); _mirrors->obj_at_put(_index, method->method_holder()->java_mirror());
*** 1498,1518 **** (Symbol*)NULL : holder->constants()->symbol_at(source_file_name_index); } // Print stack trace element to resource allocated buffer char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, ! int method_id, int version, int bci, int cpref) { // Get strings and string lengths InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); const char* klass_name = holder->external_name(); int buf_len = (int)strlen(klass_name); ! Method* method = holder->method_with_orig_idnum(method_id, version); ! ! // The method can be NULL if the requested class version is gone ! Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); char* method_name = sym->as_C_string(); buf_len += (int)strlen(method_name); char* source_file_name = NULL; Symbol* source = get_source_file_name(holder, version); --- 1509,1526 ---- (Symbol*)NULL : holder->constants()->symbol_at(source_file_name_index); } // Print stack trace element to resource allocated buffer char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, ! const methodHandle& method, int version, int bci) { // Get strings and string lengths InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); const char* klass_name = holder->external_name(); int buf_len = (int)strlen(klass_name); ! Symbol* sym = method->name(); char* method_name = sym->as_C_string(); buf_len += (int)strlen(method_name); char* source_file_name = NULL; Symbol* source = get_source_file_name(holder, version);
*** 1525,1537 **** char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); // Print stack trace line in buffer sprintf(buf, "\tat %s.%s", klass_name, method_name); - if (!version_matches(method, version)) { - strcat(buf, "(Redefined)"); - } else { int line_number = get_line_number(method, bci); if (line_number == -2) { strcat(buf, "(Native Method)"); } else { if (source_file_name != NULL && (line_number != -1)) { --- 1533,1542 ----
*** 1547,1574 **** nmethod* nm = method->code(); if (WizardMode && nm != NULL) { sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); } } - } return buf; } void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, ! int method_id, int version, int bci, int cpref) { ResourceMark rm; ! char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci, cpref); st->print_cr("%s", buf); } void java_lang_Throwable::print_stack_element(outputStream *st, const methodHandle& method, int bci) { Handle mirror = method->method_holder()->java_mirror(); - int method_id = method->orig_method_idnum(); int version = method->constants()->version(); ! int cpref = method->name_index(); ! print_stack_element(st, mirror, method_id, version, bci, cpref); } const char* java_lang_Throwable::no_stack_trace_message() { return "\t<<no stack trace available>>"; } --- 1552,1576 ---- nmethod* nm = method->code(); if (WizardMode && nm != NULL) { sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); } } return buf; } void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, ! const methodHandle& method, int version, int bci) { ResourceMark rm; ! char* buf = print_stack_element_to_buffer(mirror, method, version, bci); st->print_cr("%s", buf); } void java_lang_Throwable::print_stack_element(outputStream *st, const methodHandle& method, int bci) { Handle mirror = method->method_holder()->java_mirror(); int version = method->constants()->version(); ! print_stack_element(st, mirror, method, version, bci); } const char* java_lang_Throwable::no_stack_trace_message() { return "\t<<no stack trace available>>"; }
*** 1589,1610 **** // Get method id, bci, version and mirror from chunk typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); - typeArrayHandle cprefs (THREAD, BacktraceBuilder::get_cprefs(result)); int length = methods()->length(); for (int index = 0; index < length; index++) { Handle mirror(THREAD, mirrors->obj_at(index)); // NULL mirror means end of stack trace if (mirror.is_null()) goto handle_cause; ! int method = methods->short_at(index); int version = version_at(bcis->int_at(index)); int bci = bci_at(bcis->int_at(index)); ! int cpref = cprefs->short_at(index); ! print_stack_element(st, mirror, method, version, bci, cpref); } result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); } handle_cause: { --- 1591,1610 ---- // Get method id, bci, version and mirror from chunk typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); int length = methods()->length(); for (int index = 0; index < length; index++) { Handle mirror(THREAD, mirrors->obj_at(index)); // NULL mirror means end of stack trace if (mirror.is_null()) goto handle_cause; ! methodHandle method(THREAD, (Method*)methods->metadata_at(index)); int version = version_at(bcis->int_at(index)); int bci = bci_at(bcis->int_at(index)); ! print_stack_element(st, mirror, method, version, bci); } result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); } handle_cause: {
*** 1643,1653 **** // This is unnecessary in 1.7+ but harmless clear_stacktrace(throwable()); int max_depth = MaxJavaStackTraceDepth; JavaThread* thread = (JavaThread*)THREAD; ! BacktraceBuilder bt(CHECK); // If there is no Java frame just return the method that was being called // with bci 0 if (!thread->has_last_Java_frame()) { if (max_depth >= 1 && method() != NULL) { --- 1643,1653 ---- // This is unnecessary in 1.7+ but harmless clear_stacktrace(throwable()); int max_depth = MaxJavaStackTraceDepth; JavaThread* thread = (JavaThread*)THREAD; ! BacktraceBuilder bt(throwable, CHECK); // If there is no Java frame just return the method that was being called // with bci 0 if (!thread->has_last_Java_frame()) { if (max_depth >= 1 && method() != NULL) {
*** 1785,1795 **** void java_lang_Throwable::allocate_backtrace(Handle throwable, TRAPS) { // Allocate stack trace - backtrace is created but not filled in // No-op if stack trace is disabled if (!StackTraceInThrowable) return; ! BacktraceBuilder bt(CHECK); // creates a backtrace set_backtrace(throwable(), bt.backtrace()); } void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle throwable) { --- 1785,1795 ---- void java_lang_Throwable::allocate_backtrace(Handle throwable, TRAPS) { // Allocate stack trace - backtrace is created but not filled in // No-op if stack trace is disabled if (!StackTraceInThrowable) return; ! BacktraceBuilder bt(throwable, CHECK); // creates a backtrace set_backtrace(throwable(), bt.backtrace()); } void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle throwable) {
*** 1876,1909 **** skip_chunks--; } if (chunk == NULL) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } ! // Get method id, bci, version, mirror and cpref from chunk typeArrayOop methods = BacktraceBuilder::get_methods(chunk); typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); - typeArrayOop cprefs = BacktraceBuilder::get_cprefs(chunk); assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); ! int method = methods->short_at(chunk_index); int version = version_at(bcis->int_at(chunk_index)); int bci = bci_at(bcis->int_at(chunk_index)); - int cpref = cprefs->short_at(chunk_index); Handle mirror(THREAD, mirrors->obj_at(chunk_index)); // Chunk can be partial full if (mirror.is_null()) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } ! oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, cpref, CHECK_0); return element; } ! oop java_lang_StackTraceElement::create(Handle mirror, int method_id, ! int version, int bci, int cpref, TRAPS) { // Allocate java.lang.StackTraceElement instance Klass* k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); instanceKlassHandle ik (THREAD, k); if (ik->should_be_initialized()) { --- 1876,1907 ---- skip_chunks--; } if (chunk == NULL) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } ! // Get method id, bci, version, mirror from chunk typeArrayOop methods = BacktraceBuilder::get_methods(chunk); typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); ! methodHandle method(THREAD, (Method*)methods->metadata_at(chunk_index)); int version = version_at(bcis->int_at(chunk_index)); int bci = bci_at(bcis->int_at(chunk_index)); Handle mirror(THREAD, mirrors->obj_at(chunk_index)); // Chunk can be partial full if (mirror.is_null()) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } ! oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, CHECK_0); return element; } ! oop java_lang_StackTraceElement::create(Handle mirror, const methodHandle& method, ! int version, int bci, TRAPS) { // Allocate java.lang.StackTraceElement instance Klass* k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); instanceKlassHandle ik (THREAD, k); if (ik->should_be_initialized()) {
*** 1916,1957 **** InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); const char* str = holder->external_name(); oop classname = StringTable::intern((char*) str, CHECK_0); java_lang_StackTraceElement::set_declaringClass(element(), classname); - Method* method = holder->method_with_orig_idnum(method_id, version); - - // The method can be NULL if the requested class version is gone - Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); - // Fill in method name ! oop methodname = StringTable::intern(sym, CHECK_0); java_lang_StackTraceElement::set_methodName(element(), methodname); - if (!version_matches(method, version)) { - // The method was redefined, accurate line number information isn't available - java_lang_StackTraceElement::set_fileName(element(), NULL); - java_lang_StackTraceElement::set_lineNumber(element(), -1); - } else { // Fill in source file name and line number. Symbol* source = get_source_file_name(holder, version); if (ShowHiddenFrames && source == NULL) source = vmSymbols::unknown_class_name(); oop filename = StringTable::intern(source, CHECK_0); java_lang_StackTraceElement::set_fileName(element(), filename); int line_number = get_line_number(method, bci); java_lang_StackTraceElement::set_lineNumber(element(), line_number); - } return element(); } oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) { Handle mirror (THREAD, method->method_holder()->java_mirror()); ! int method_id = method->orig_method_idnum(); ! int cpref = method->name_index(); ! return create(mirror, method_id, method->constants()->version(), bci, cpref, THREAD); } void java_lang_reflect_AccessibleObject::compute_offsets() { Klass* k = SystemDictionary::reflect_AccessibleObject_klass(); compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature()); --- 1914,1942 ---- InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); const char* str = holder->external_name(); oop classname = StringTable::intern((char*) str, CHECK_0); java_lang_StackTraceElement::set_declaringClass(element(), classname); // Fill in method name ! oop methodname = StringTable::intern(method->name(), CHECK_0); java_lang_StackTraceElement::set_methodName(element(), methodname); // Fill in source file name and line number. Symbol* source = get_source_file_name(holder, version); if (ShowHiddenFrames && source == NULL) source = vmSymbols::unknown_class_name(); oop filename = StringTable::intern(source, CHECK_0); java_lang_StackTraceElement::set_fileName(element(), filename); int line_number = get_line_number(method, bci); java_lang_StackTraceElement::set_lineNumber(element(), line_number); return element(); } oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) { Handle mirror (THREAD, method->method_holder()->java_mirror()); ! return create(mirror, method, method->constants()->version(), bci, THREAD); } void java_lang_reflect_AccessibleObject::compute_offsets() { Klass* k = SystemDictionary::reflect_AccessibleObject_klass(); compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature());
src/share/vm/classfile/javaClasses.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File