--- old/src/share/vm/classfile/javaClasses.cpp 2015-11-16 17:05:16.510492874 -0500 +++ new/src/share/vm/classfile/javaClasses.cpp 2015-11-16 17:05:16.165778454 -0500 @@ -1362,7 +1362,7 @@ typeArrayOop _methods; typeArrayOop _bcis; objArrayOop _mirrors; - typeArrayOop _cprefs; // needed to insulate method name against redefinition + typeArrayOop _names; // needed to insulate method name against redefinition int _index; No_Safepoint_Verifier _nsv; @@ -1372,7 +1372,7 @@ 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_names_offset = java_lang_Throwable::trace_names_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 @@ -1394,14 +1394,14 @@ 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; + static typeArrayOop get_names(objArrayHandle chunk) { + typeArrayOop names = typeArrayOop(chunk->obj_at(trace_names_offset)); + assert(names != NULL, "names array should be initialized in backtrace"); + return names; } // constructor for new backtrace - BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _cprefs(NULL) { + BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _names(NULL) { expand(CHECK); _backtrace = _head; _index = 0; @@ -1411,7 +1411,7 @@ _methods = get_methods(backtrace); _bcis = get_bcis(backtrace); _mirrors = get_mirrors(backtrace); - _cprefs = get_cprefs(backtrace); + _names = get_names(backtrace); assert(_methods->length() == _bcis->length() && _methods->length() == _mirrors->length(), "method and source information arrays should match"); @@ -1437,8 +1437,8 @@ 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); + typeArrayOop names = oopFactory::new_symbolArray(trace_chunk_size, CHECK); + typeArrayHandle new_names(THREAD, names); if (!old_head.is_null()) { old_head->obj_at_put(trace_next_offset, new_head()); @@ -1446,13 +1446,13 @@ 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()); + new_head->obj_at_put(trace_names_offset, new_names()); _head = new_head(); _methods = new_methods(); _bcis = new_bcis(); _mirrors = new_mirrors(); - _cprefs = new_cprefs(); + _names = new_names(); _index = 0; } @@ -1474,7 +1474,11 @@ _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 can store Symbol* in the backtrace without additional refcounting because the + // Symbol* for the name is kept alive because the class containing the method is kept + // alive via. the mirror. Since redefinition does not allow deleting methods, the new + // class will also have this name, somewhere, maybe not at the same constant pool index. + _names->symbol_at_put(_index, method->name()); // We need to save the mirrors in the backtrace to keep the class // from being unloaded while we still have this stack trace. @@ -1499,8 +1503,7 @@ } // 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) { +char* print_stack_element_to_buffer(Handle mirror, int method_id, int version, int bci, Symbol* name) { // Get strings and string lengths InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); @@ -1509,9 +1512,7 @@ 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(); + char* method_name = name->as_C_string(); buf_len += (int)strlen(method_name); char* source_file_name = NULL; @@ -1554,10 +1555,10 @@ return buf; } -void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, - int method_id, int version, int bci, int cpref) { +void print_stack_element_internal(outputStream *st, Handle mirror, + int method_id, int version, int bci, Symbol* name) { ResourceMark rm; - char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci, cpref); + char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci, name); st->print_cr("%s", buf); } @@ -1565,12 +1566,8 @@ 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<>"; + Symbol *name = method->name(); + print_stack_element_internal(st, mirror, method_id, version, bci, name); } @@ -1581,7 +1578,7 @@ while (h_throwable.not_null()) { objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable()))); if (result.is_null()) { - st->print_raw_cr(no_stack_trace_message()); + st->print_raw_cr("\t<>"); return; } @@ -1591,7 +1588,7 @@ 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)); + typeArrayHandle names (THREAD, BacktraceBuilder::get_names(result)); int length = methods()->length(); for (int index = 0; index < length; index++) { @@ -1601,8 +1598,8 @@ 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); + Symbol* name = names->symbol_at(index); + print_stack_element_internal(st, mirror, method, version, bci, name); } result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); } @@ -1878,30 +1875,30 @@ if (chunk == NULL) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } - // Get method id, bci, version, mirror and cpref from chunk + // Get method id, bci, version, mirror and name 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); + typeArrayOop names = BacktraceBuilder::get_names(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); + Symbol* name = names->symbol_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); + oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, name, CHECK_0); return element; } oop java_lang_StackTraceElement::create(Handle mirror, int method_id, - int version, int bci, int cpref, TRAPS) { + int version, int bci, Symbol* name, TRAPS) { // Allocate java.lang.StackTraceElement instance Klass* k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); @@ -1918,15 +1915,13 @@ 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); + oop methodname = StringTable::intern(name, CHECK_0); java_lang_StackTraceElement::set_methodName(element(), methodname); + // The method can be NULL if the requested class version is gone + Method* method = holder->method_with_orig_idnum(method_id, version); if (!version_matches(method, version)) { // The method was redefined, accurate line number information isn't available java_lang_StackTraceElement::set_fileName(element(), NULL); @@ -1948,8 +1943,8 @@ 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); + Symbol* name = method->name(); + return create(mirror, method_id, method->constants()->version(), bci, name, THREAD); } void java_lang_reflect_AccessibleObject::compute_offsets() {