1643 _index++; |
1653 _index++; |
1644 } |
1654 } |
1645 |
1655 |
1646 }; |
1656 }; |
1647 |
1657 |
|
1658 struct BacktraceElement : public StackObj { |
|
1659 int _method_id; |
|
1660 int _bci; |
|
1661 int _version; |
|
1662 int _cpref; |
|
1663 Handle _mirror; |
|
1664 BacktraceElement(Handle mirror, int mid, int version, int bci, int cpref) : |
|
1665 _mirror(mirror), _method_id(mid), _version(version), _bci(bci), _cpref(cpref) {} |
|
1666 }; |
|
1667 |
|
1668 class BacktraceIterator : public StackObj { |
|
1669 int _index; |
|
1670 objArrayHandle _result; |
|
1671 objArrayHandle _mirrors; |
|
1672 typeArrayHandle _methods; |
|
1673 typeArrayHandle _bcis; |
|
1674 typeArrayHandle _cprefs; |
|
1675 |
|
1676 void init(objArrayHandle result, Thread* thread) { |
|
1677 // Get method id, bci, version and mirror from chunk |
|
1678 _result = result; |
|
1679 if (_result.not_null()) { |
|
1680 _methods = typeArrayHandle(thread, BacktraceBuilder::get_methods(_result)); |
|
1681 _bcis = typeArrayHandle(thread, BacktraceBuilder::get_bcis(_result)); |
|
1682 _mirrors = objArrayHandle(thread, BacktraceBuilder::get_mirrors(_result)); |
|
1683 _cprefs = typeArrayHandle(thread, BacktraceBuilder::get_cprefs(_result)); |
|
1684 _index = 0; |
|
1685 } |
|
1686 } |
|
1687 public: |
|
1688 BacktraceIterator(objArrayHandle result, Thread* thread) { |
|
1689 init(result, thread); |
|
1690 assert(_methods->length() == java_lang_Throwable::trace_chunk_size, "lengths don't match"); |
|
1691 } |
|
1692 |
|
1693 BacktraceElement next(Thread* thread) { |
|
1694 BacktraceElement e (Handle(thread, _mirrors->obj_at(_index)), |
|
1695 _methods->short_at(_index), |
|
1696 Backtrace::version_at(_bcis->int_at(_index)), |
|
1697 Backtrace::bci_at(_bcis->int_at(_index)), |
|
1698 _cprefs->short_at(_index)); |
|
1699 _index++; |
|
1700 |
|
1701 if (_index >= java_lang_Throwable::trace_chunk_size) { |
|
1702 int next_offset = java_lang_Throwable::trace_next_offset; |
|
1703 // Get next chunk |
|
1704 objArrayHandle result (thread, objArrayOop(_result->obj_at(next_offset))); |
|
1705 init(result, thread); |
|
1706 } |
|
1707 return e; |
|
1708 } |
|
1709 |
|
1710 bool repeat() { |
|
1711 return _result.not_null() && _mirrors->obj_at(_index) != NULL; |
|
1712 } |
|
1713 }; |
|
1714 |
|
1715 |
1648 // Print stack trace element to resource allocated buffer |
1716 // Print stack trace element to resource allocated buffer |
1649 char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, |
1717 static void print_stack_element_to_stream(outputStream* st, Handle mirror, int method_id, |
1650 int method_id, int version, int bci, int cpref) { |
1718 int version, int bci, int cpref) { |
|
1719 ResourceMark rm; |
1651 |
1720 |
1652 // Get strings and string lengths |
1721 // Get strings and string lengths |
1653 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
1722 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
1654 const char* klass_name = holder->external_name(); |
1723 const char* klass_name = holder->external_name(); |
1655 int buf_len = (int)strlen(klass_name); |
1724 int buf_len = (int)strlen(klass_name); |
1732 // Now print the stack trace. |
1791 // Now print the stack trace. |
1733 Thread* THREAD = Thread::current(); |
1792 Thread* THREAD = Thread::current(); |
1734 while (throwable.not_null()) { |
1793 while (throwable.not_null()) { |
1735 objArrayHandle result (THREAD, objArrayOop(backtrace(throwable()))); |
1794 objArrayHandle result (THREAD, objArrayOop(backtrace(throwable()))); |
1736 if (result.is_null()) { |
1795 if (result.is_null()) { |
1737 st->print_raw_cr(no_stack_trace_message()); |
1796 st->print_raw_cr("\t<<no stack trace available>>"); |
1738 return; |
1797 return; |
1739 } |
1798 } |
1740 |
1799 BacktraceIterator iter(result, THREAD); |
1741 while (result.not_null()) { |
1800 |
1742 // Get method id, bci, version and mirror from chunk |
1801 while (iter.repeat()) { |
1743 typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); |
1802 BacktraceElement bte = iter.next(THREAD); |
1744 typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); |
1803 print_stack_element_to_stream(st, bte._mirror, bte._method_id, bte._version, bte._bci, bte._cpref); |
1745 objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); |
1804 } |
1746 typeArrayHandle cprefs (THREAD, BacktraceBuilder::get_cprefs(result)); |
|
1747 |
|
1748 int length = methods()->length(); |
|
1749 for (int index = 0; index < length; index++) { |
|
1750 Handle mirror(THREAD, mirrors->obj_at(index)); |
|
1751 // NULL mirror means end of stack trace |
|
1752 if (mirror.is_null()) goto handle_cause; |
|
1753 int method = methods->short_at(index); |
|
1754 int version = Backtrace::version_at(bcis->int_at(index)); |
|
1755 int bci = Backtrace::bci_at(bcis->int_at(index)); |
|
1756 int cpref = cprefs->short_at(index); |
|
1757 print_stack_element(st, mirror, method, version, bci, cpref); |
|
1758 } |
|
1759 result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); |
|
1760 } |
|
1761 handle_cause: |
|
1762 { |
1805 { |
|
1806 // Call getCause() which doesn't necessarily return the _cause field. |
1763 EXCEPTION_MARK; |
1807 EXCEPTION_MARK; |
1764 JavaValue cause(T_OBJECT); |
1808 JavaValue cause(T_OBJECT); |
1765 JavaCalls::call_virtual(&cause, |
1809 JavaCalls::call_virtual(&cause, |
1766 throwable, |
1810 throwable, |
1767 KlassHandle(THREAD, throwable->klass()), |
1811 KlassHandle(THREAD, throwable->klass()), |
1978 |
2028 |
1979 // Unlike fill_in_stack_trace we do not skip fillInStackTrace or throwable init |
2029 // Unlike fill_in_stack_trace we do not skip fillInStackTrace or throwable init |
1980 // methods as preallocated errors aren't created by "java" code. |
2030 // methods as preallocated errors aren't created by "java" code. |
1981 |
2031 |
1982 // fill in as much stack trace as possible |
2032 // fill in as much stack trace as possible |
1983 typeArrayOop methods = BacktraceBuilder::get_methods(backtrace); |
|
1984 int max_chunks = MIN2(methods->length(), (int)MaxJavaStackTraceDepth); |
|
1985 int chunk_count = 0; |
2033 int chunk_count = 0; |
1986 |
|
1987 for (;!st.at_end(); st.next()) { |
2034 for (;!st.at_end(); st.next()) { |
1988 bt.push(st.method(), st.bci(), CHECK); |
2035 bt.push(st.method(), st.bci(), CHECK); |
1989 chunk_count++; |
2036 chunk_count++; |
1990 |
2037 |
1991 // Bail-out for deep stacks |
2038 // Bail-out for deep stacks |
1992 if (chunk_count >= max_chunks) break; |
2039 if (chunk_count >= trace_chunk_size) break; |
1993 } |
2040 } |
|
2041 set_depth(throwable(), chunk_count); |
|
2042 log_info(stacktrace)("%s, %d", throwable->klass()->external_name(), chunk_count); |
1994 |
2043 |
1995 // We support the Throwable immutability protocol defined for Java 7. |
2044 // We support the Throwable immutability protocol defined for Java 7. |
1996 java_lang_Throwable::set_stacktrace(throwable(), java_lang_Throwable::unassigned_stacktrace()); |
2045 java_lang_Throwable::set_stacktrace(throwable(), java_lang_Throwable::unassigned_stacktrace()); |
1997 assert(java_lang_Throwable::unassigned_stacktrace() != NULL, "not initialized"); |
2046 assert(java_lang_Throwable::unassigned_stacktrace() != NULL, "not initialized"); |
1998 } |
2047 } |
1999 |
2048 |
2000 |
2049 void java_lang_Throwable::get_stack_trace_elements(Handle throwable, |
2001 int java_lang_Throwable::get_stack_trace_depth(oop throwable, TRAPS) { |
2050 objArrayHandle stack_trace_array_h, TRAPS) { |
2002 if (throwable == NULL) { |
2051 |
2003 THROW_0(vmSymbols::java_lang_NullPointerException()); |
2052 if (throwable.is_null() || stack_trace_array_h.is_null()) { |
2004 } |
2053 THROW(vmSymbols::java_lang_NullPointerException()); |
2005 objArrayOop chunk = objArrayOop(backtrace(throwable)); |
2054 } |
2006 int depth = 0; |
2055 |
2007 if (chunk != NULL) { |
2056 assert(stack_trace_array_h->is_objArray(), "Stack trace array should be an array of StackTraceElenent"); |
2008 // Iterate over chunks and count full ones |
2057 |
2009 while (true) { |
2058 if (stack_trace_array_h->length() != depth(throwable())) { |
2010 objArrayOop next = objArrayOop(chunk->obj_at(trace_next_offset)); |
2059 THROW(vmSymbols::java_lang_IndexOutOfBoundsException()); |
2011 if (next == NULL) break; |
2060 } |
2012 depth += trace_chunk_size; |
2061 |
2013 chunk = next; |
2062 objArrayHandle result(THREAD, objArrayOop(backtrace(throwable()))); |
2014 } |
2063 BacktraceIterator iter(result, THREAD); |
2015 assert(chunk != NULL && chunk->obj_at(trace_next_offset) == NULL, "sanity check"); |
2064 |
2016 // Count element in remaining partial chunk. NULL value for mirror |
2065 int index = 0; |
2017 // marks the end of the stack trace elements that are saved. |
2066 while (iter.repeat()) { |
2018 objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); |
2067 BacktraceElement bte = iter.next(THREAD); |
2019 assert(mirrors != NULL, "sanity check"); |
2068 |
2020 for (int i = 0; i < mirrors->length(); i++) { |
2069 Handle stack_trace_element(THREAD, stack_trace_array_h->obj_at(index++)); |
2021 if (mirrors->obj_at(i) == NULL) break; |
2070 |
2022 depth++; |
2071 if (stack_trace_element.is_null()) { |
2023 } |
2072 THROW(vmSymbols::java_lang_NullPointerException()); |
2024 } |
2073 } |
2025 return depth; |
2074 |
2026 } |
2075 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(bte._mirror())); |
2027 |
2076 methodHandle method (THREAD, holder->method_with_orig_idnum(bte._method_id, bte._version)); |
2028 |
2077 |
2029 oop java_lang_Throwable::get_stack_trace_element(oop throwable, int index, TRAPS) { |
2078 java_lang_StackTraceElement::fill_in(stack_trace_element, holder, |
2030 if (throwable == NULL) { |
2079 method, |
2031 THROW_0(vmSymbols::java_lang_NullPointerException()); |
2080 bte._version, |
2032 } |
2081 bte._bci, |
2033 if (index < 0) { |
2082 bte._cpref, CHECK); |
2034 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); |
2083 } |
2035 } |
2084 } |
2036 // Compute how many chunks to skip and index into actual chunk |
2085 |
2037 objArrayOop chunk = objArrayOop(backtrace(throwable)); |
2086 oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) { |
2038 int skip_chunks = index / trace_chunk_size; |
|
2039 int chunk_index = index % trace_chunk_size; |
|
2040 while (chunk != NULL && skip_chunks > 0) { |
|
2041 chunk = objArrayOop(chunk->obj_at(trace_next_offset)); |
|
2042 skip_chunks--; |
|
2043 } |
|
2044 if (chunk == NULL) { |
|
2045 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); |
|
2046 } |
|
2047 // Get method id, bci, version, mirror and cpref from chunk |
|
2048 typeArrayOop methods = BacktraceBuilder::get_methods(chunk); |
|
2049 typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); |
|
2050 objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); |
|
2051 typeArrayOop cprefs = BacktraceBuilder::get_cprefs(chunk); |
|
2052 |
|
2053 assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); |
|
2054 |
|
2055 int method = methods->short_at(chunk_index); |
|
2056 int version = Backtrace::version_at(bcis->int_at(chunk_index)); |
|
2057 int bci = Backtrace::bci_at(bcis->int_at(chunk_index)); |
|
2058 int cpref = cprefs->short_at(chunk_index); |
|
2059 Handle mirror(THREAD, mirrors->obj_at(chunk_index)); |
|
2060 |
|
2061 // Chunk can be partial full |
|
2062 if (mirror.is_null()) { |
|
2063 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); |
|
2064 } |
|
2065 oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, cpref, CHECK_0); |
|
2066 return element; |
|
2067 } |
|
2068 |
|
2069 oop java_lang_StackTraceElement::create(Handle mirror, int method_id, |
|
2070 int version, int bci, int cpref, TRAPS) { |
|
2071 // Allocate java.lang.StackTraceElement instance |
2087 // Allocate java.lang.StackTraceElement instance |
2072 Klass* k = SystemDictionary::StackTraceElement_klass(); |
2088 Klass* k = SystemDictionary::StackTraceElement_klass(); |
2073 assert(k != NULL, "must be loaded in 1.4+"); |
2089 assert(k != NULL, "must be loaded in 1.4+"); |
2074 instanceKlassHandle ik (THREAD, k); |
2090 instanceKlassHandle ik (THREAD, k); |
2075 if (ik->should_be_initialized()) { |
2091 if (ik->should_be_initialized()) { |
2076 ik->initialize(CHECK_0); |
2092 ik->initialize(CHECK_0); |
2077 } |
2093 } |
2078 |
2094 |
2079 Handle element = ik->allocate_instance_handle(CHECK_0); |
2095 Handle element = ik->allocate_instance_handle(CHECK_0); |
2080 |
2096 |
|
2097 int cpref = method->name_index(); |
|
2098 int version = method->constants()->version(); |
|
2099 fill_in(element, method->method_holder(), method, version, bci, cpref, CHECK_0); |
|
2100 return element(); |
|
2101 } |
|
2102 |
|
2103 void java_lang_StackTraceElement::fill_in(Handle element, |
|
2104 InstanceKlass* holder, const methodHandle& method, |
|
2105 int version, int bci, int cpref, TRAPS) { |
|
2106 assert(element->is_a(SystemDictionary::StackTraceElement_klass()), "sanity check"); |
|
2107 |
2081 // Fill in class name |
2108 // Fill in class name |
2082 ResourceMark rm(THREAD); |
2109 ResourceMark rm(THREAD); |
2083 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
|
2084 const char* str = holder->external_name(); |
2110 const char* str = holder->external_name(); |
2085 oop classname = StringTable::intern((char*) str, CHECK_0); |
2111 oop classname = StringTable::intern((char*) str, CHECK); |
2086 java_lang_StackTraceElement::set_declaringClass(element(), classname); |
2112 java_lang_StackTraceElement::set_declaringClass(element(), classname); |
2087 |
2113 |
2088 Method* method = holder->method_with_orig_idnum(method_id, version); |
|
2089 |
|
2090 // The method can be NULL if the requested class version is gone |
2114 // The method can be NULL if the requested class version is gone |
2091 Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); |
2115 Symbol* sym = !method.is_null() ? method->name() : holder->constants()->symbol_at(cpref); |
2092 |
2116 |
2093 // Fill in method name |
2117 // Fill in method name |
2094 oop methodname = StringTable::intern(sym, CHECK_0); |
2118 oop methodname = StringTable::intern(sym, CHECK); |
2095 java_lang_StackTraceElement::set_methodName(element(), methodname); |
2119 java_lang_StackTraceElement::set_methodName(element(), methodname); |
2096 |
2120 |
2097 if (!version_matches(method, version)) { |
2121 if (!version_matches(method(), version)) { |
2098 // The method was redefined, accurate line number information isn't available |
2122 // The method was redefined, accurate line number information isn't available |
2099 java_lang_StackTraceElement::set_fileName(element(), NULL); |
2123 java_lang_StackTraceElement::set_fileName(element(), NULL); |
2100 java_lang_StackTraceElement::set_lineNumber(element(), -1); |
2124 java_lang_StackTraceElement::set_lineNumber(element(), -1); |
2101 } else { |
2125 } else { |
2102 // Fill in source file name and line number. |
2126 // Fill in source file name and line number. |
2103 Symbol* source = Backtrace::get_source_file_name(holder, version); |
2127 Symbol* source = Backtrace::get_source_file_name(holder, version); |
2104 if (ShowHiddenFrames && source == NULL) |
2128 if (ShowHiddenFrames && source == NULL) |
2105 source = vmSymbols::unknown_class_name(); |
2129 source = vmSymbols::unknown_class_name(); |
2106 oop filename = StringTable::intern(source, CHECK_0); |
2130 oop filename = StringTable::intern(source, CHECK); |
2107 java_lang_StackTraceElement::set_fileName(element(), filename); |
2131 java_lang_StackTraceElement::set_fileName(element(), filename); |
2108 |
2132 |
2109 int line_number = Backtrace::get_line_number(method, bci); |
2133 int line_number = Backtrace::get_line_number(method, bci); |
2110 java_lang_StackTraceElement::set_lineNumber(element(), line_number); |
2134 java_lang_StackTraceElement::set_lineNumber(element(), line_number); |
2111 } |
2135 } |
2112 return element(); |
|
2113 } |
|
2114 |
|
2115 oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) { |
|
2116 Handle mirror (THREAD, method->method_holder()->java_mirror()); |
|
2117 int method_id = method->orig_method_idnum(); |
|
2118 int cpref = method->name_index(); |
|
2119 return create(mirror, method_id, method->constants()->version(), bci, cpref, THREAD); |
|
2120 } |
2136 } |
2121 |
2137 |
2122 Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) { |
2138 Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) { |
2123 if (MemberNameInStackFrame) { |
2139 if (MemberNameInStackFrame) { |
2124 Handle mname(THREAD, stackFrame->obj_field(_memberName_offset)); |
2140 Handle mname(THREAD, stackFrame->obj_field(_memberName_offset)); |