1 /* |
1 /* |
2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
1576 Handle _backtrace; |
1576 Handle _backtrace; |
1577 objArrayOop _head; |
1577 objArrayOop _head; |
1578 typeArrayOop _methods; |
1578 typeArrayOop _methods; |
1579 typeArrayOop _bcis; |
1579 typeArrayOop _bcis; |
1580 objArrayOop _mirrors; |
1580 objArrayOop _mirrors; |
1581 typeArrayOop _cprefs; // needed to insulate method name against redefinition |
1581 typeArrayOop _names; // needed to insulate method name against redefinition |
1582 int _index; |
1582 int _index; |
1583 NoSafepointVerifier _nsv; |
1583 NoSafepointVerifier _nsv; |
1584 |
1584 |
1585 enum { |
1585 enum { |
1586 trace_methods_offset = java_lang_Throwable::trace_methods_offset, |
1586 trace_methods_offset = java_lang_Throwable::trace_methods_offset, |
1587 trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, |
1587 trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, |
1588 trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, |
1588 trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, |
1589 trace_cprefs_offset = java_lang_Throwable::trace_cprefs_offset, |
1589 trace_names_offset = java_lang_Throwable::trace_names_offset, |
1590 trace_next_offset = java_lang_Throwable::trace_next_offset, |
1590 trace_next_offset = java_lang_Throwable::trace_next_offset, |
1591 trace_size = java_lang_Throwable::trace_size, |
1591 trace_size = java_lang_Throwable::trace_size, |
1592 trace_chunk_size = java_lang_Throwable::trace_chunk_size |
1592 trace_chunk_size = java_lang_Throwable::trace_chunk_size |
1593 }; |
1593 }; |
1594 |
1594 |
1606 static objArrayOop get_mirrors(objArrayHandle chunk) { |
1606 static objArrayOop get_mirrors(objArrayHandle chunk) { |
1607 objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); |
1607 objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); |
1608 assert(mirrors != NULL, "mirror array should be initialized in backtrace"); |
1608 assert(mirrors != NULL, "mirror array should be initialized in backtrace"); |
1609 return mirrors; |
1609 return mirrors; |
1610 } |
1610 } |
1611 static typeArrayOop get_cprefs(objArrayHandle chunk) { |
1611 static typeArrayOop get_names(objArrayHandle chunk) { |
1612 typeArrayOop cprefs = typeArrayOop(chunk->obj_at(trace_cprefs_offset)); |
1612 typeArrayOop names = typeArrayOop(chunk->obj_at(trace_names_offset)); |
1613 assert(cprefs != NULL, "cprefs array should be initialized in backtrace"); |
1613 assert(names != NULL, "names array should be initialized in backtrace"); |
1614 return cprefs; |
1614 return names; |
1615 } |
1615 } |
1616 |
1616 |
1617 public: |
1617 public: |
1618 |
1618 |
1619 // constructor for new backtrace |
1619 // constructor for new backtrace |
1620 BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _cprefs(NULL) { |
1620 BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _names(NULL) { |
1621 expand(CHECK); |
1621 expand(CHECK); |
1622 _backtrace = _head; |
1622 _backtrace = _head; |
1623 _index = 0; |
1623 _index = 0; |
1624 } |
1624 } |
1625 |
1625 |
1626 BacktraceBuilder(objArrayHandle backtrace) { |
1626 BacktraceBuilder(objArrayHandle backtrace) { |
1627 _methods = get_methods(backtrace); |
1627 _methods = get_methods(backtrace); |
1628 _bcis = get_bcis(backtrace); |
1628 _bcis = get_bcis(backtrace); |
1629 _mirrors = get_mirrors(backtrace); |
1629 _mirrors = get_mirrors(backtrace); |
1630 _cprefs = get_cprefs(backtrace); |
1630 _names = get_names(backtrace); |
1631 assert(_methods->length() == _bcis->length() && |
1631 assert(_methods->length() == _bcis->length() && |
1632 _methods->length() == _mirrors->length(), |
1632 _methods->length() == _mirrors->length() && |
|
1633 _mirrors->length() == _names->length(), |
1633 "method and source information arrays should match"); |
1634 "method and source information arrays should match"); |
1634 |
1635 |
1635 // head is the preallocated backtrace |
1636 // head is the preallocated backtrace |
1636 _backtrace = _head = backtrace(); |
1637 _backtrace = _head = backtrace(); |
1637 _index = 0; |
1638 _index = 0; |
1651 typeArrayHandle new_bcis(THREAD, bcis); |
1652 typeArrayHandle new_bcis(THREAD, bcis); |
1652 |
1653 |
1653 objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); |
1654 objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); |
1654 objArrayHandle new_mirrors(THREAD, mirrors); |
1655 objArrayHandle new_mirrors(THREAD, mirrors); |
1655 |
1656 |
1656 typeArrayOop cprefs = oopFactory::new_shortArray(trace_chunk_size, CHECK); |
1657 typeArrayOop names = oopFactory::new_symbolArray(trace_chunk_size, CHECK); |
1657 typeArrayHandle new_cprefs(THREAD, cprefs); |
1658 typeArrayHandle new_names(THREAD, names); |
1658 |
1659 |
1659 if (!old_head.is_null()) { |
1660 if (!old_head.is_null()) { |
1660 old_head->obj_at_put(trace_next_offset, new_head()); |
1661 old_head->obj_at_put(trace_next_offset, new_head()); |
1661 } |
1662 } |
1662 new_head->obj_at_put(trace_methods_offset, new_methods()); |
1663 new_head->obj_at_put(trace_methods_offset, new_methods()); |
1663 new_head->obj_at_put(trace_bcis_offset, new_bcis()); |
1664 new_head->obj_at_put(trace_bcis_offset, new_bcis()); |
1664 new_head->obj_at_put(trace_mirrors_offset, new_mirrors()); |
1665 new_head->obj_at_put(trace_mirrors_offset, new_mirrors()); |
1665 new_head->obj_at_put(trace_cprefs_offset, new_cprefs()); |
1666 new_head->obj_at_put(trace_names_offset, new_names()); |
1666 |
1667 |
1667 _head = new_head(); |
1668 _head = new_head(); |
1668 _methods = new_methods(); |
1669 _methods = new_methods(); |
1669 _bcis = new_bcis(); |
1670 _bcis = new_bcis(); |
1670 _mirrors = new_mirrors(); |
1671 _mirrors = new_mirrors(); |
1671 _cprefs = new_cprefs(); |
1672 _names = new_names(); |
1672 _index = 0; |
1673 _index = 0; |
1673 } |
1674 } |
1674 |
1675 |
1675 oop backtrace() { |
1676 oop backtrace() { |
1676 return _backtrace(); |
1677 return _backtrace(); |
1688 method = mhandle(); |
1689 method = mhandle(); |
1689 } |
1690 } |
1690 |
1691 |
1691 _methods->short_at_put(_index, method->orig_method_idnum()); |
1692 _methods->short_at_put(_index, method->orig_method_idnum()); |
1692 _bcis->int_at_put(_index, Backtrace::merge_bci_and_version(bci, method->constants()->version())); |
1693 _bcis->int_at_put(_index, Backtrace::merge_bci_and_version(bci, method->constants()->version())); |
1693 _cprefs->short_at_put(_index, method->name_index()); |
1694 |
|
1695 // Note:this doesn't leak symbols because the mirror in the backtrace keeps the |
|
1696 // klass owning the symbols alive so their refcounts aren't decremented. |
|
1697 Symbol* name = method->name(); |
|
1698 _names->symbol_at_put(_index, name); |
1694 |
1699 |
1695 // We need to save the mirrors in the backtrace to keep the class |
1700 // We need to save the mirrors in the backtrace to keep the class |
1696 // from being unloaded while we still have this stack trace. |
1701 // from being unloaded while we still have this stack trace. |
1697 assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror"); |
1702 assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror"); |
1698 _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); |
1703 _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); |
1703 |
1708 |
1704 struct BacktraceElement : public StackObj { |
1709 struct BacktraceElement : public StackObj { |
1705 int _method_id; |
1710 int _method_id; |
1706 int _bci; |
1711 int _bci; |
1707 int _version; |
1712 int _version; |
1708 int _cpref; |
1713 Symbol* _name; |
1709 Handle _mirror; |
1714 Handle _mirror; |
1710 BacktraceElement(Handle mirror, int mid, int version, int bci, int cpref) : |
1715 BacktraceElement(Handle mirror, int mid, int version, int bci, Symbol* name) : |
1711 _mirror(mirror), _method_id(mid), _version(version), _bci(bci), _cpref(cpref) {} |
1716 _mirror(mirror), _method_id(mid), _version(version), _bci(bci), _name(name) {} |
1712 }; |
1717 }; |
1713 |
1718 |
1714 class BacktraceIterator : public StackObj { |
1719 class BacktraceIterator : public StackObj { |
1715 int _index; |
1720 int _index; |
1716 objArrayHandle _result; |
1721 objArrayHandle _result; |
1717 objArrayHandle _mirrors; |
1722 objArrayHandle _mirrors; |
1718 typeArrayHandle _methods; |
1723 typeArrayHandle _methods; |
1719 typeArrayHandle _bcis; |
1724 typeArrayHandle _bcis; |
1720 typeArrayHandle _cprefs; |
1725 typeArrayHandle _names; |
1721 |
1726 |
1722 void init(objArrayHandle result, Thread* thread) { |
1727 void init(objArrayHandle result, Thread* thread) { |
1723 // Get method id, bci, version and mirror from chunk |
1728 // Get method id, bci, version and mirror from chunk |
1724 _result = result; |
1729 _result = result; |
1725 if (_result.not_null()) { |
1730 if (_result.not_null()) { |
1726 _methods = typeArrayHandle(thread, BacktraceBuilder::get_methods(_result)); |
1731 _methods = typeArrayHandle(thread, BacktraceBuilder::get_methods(_result)); |
1727 _bcis = typeArrayHandle(thread, BacktraceBuilder::get_bcis(_result)); |
1732 _bcis = typeArrayHandle(thread, BacktraceBuilder::get_bcis(_result)); |
1728 _mirrors = objArrayHandle(thread, BacktraceBuilder::get_mirrors(_result)); |
1733 _mirrors = objArrayHandle(thread, BacktraceBuilder::get_mirrors(_result)); |
1729 _cprefs = typeArrayHandle(thread, BacktraceBuilder::get_cprefs(_result)); |
1734 _names = typeArrayHandle(thread, BacktraceBuilder::get_names(_result)); |
1730 _index = 0; |
1735 _index = 0; |
1731 } |
1736 } |
1732 } |
1737 } |
1733 public: |
1738 public: |
1734 BacktraceIterator(objArrayHandle result, Thread* thread) { |
1739 BacktraceIterator(objArrayHandle result, Thread* thread) { |
1739 BacktraceElement next(Thread* thread) { |
1744 BacktraceElement next(Thread* thread) { |
1740 BacktraceElement e (Handle(thread, _mirrors->obj_at(_index)), |
1745 BacktraceElement e (Handle(thread, _mirrors->obj_at(_index)), |
1741 _methods->short_at(_index), |
1746 _methods->short_at(_index), |
1742 Backtrace::version_at(_bcis->int_at(_index)), |
1747 Backtrace::version_at(_bcis->int_at(_index)), |
1743 Backtrace::bci_at(_bcis->int_at(_index)), |
1748 Backtrace::bci_at(_bcis->int_at(_index)), |
1744 _cprefs->short_at(_index)); |
1749 _names->symbol_at(_index)); |
1745 _index++; |
1750 _index++; |
1746 |
1751 |
1747 if (_index >= java_lang_Throwable::trace_chunk_size) { |
1752 if (_index >= java_lang_Throwable::trace_chunk_size) { |
1748 int next_offset = java_lang_Throwable::trace_next_offset; |
1753 int next_offset = java_lang_Throwable::trace_next_offset; |
1749 // Get next chunk |
1754 // Get next chunk |
1759 }; |
1764 }; |
1760 |
1765 |
1761 |
1766 |
1762 // Print stack trace element to resource allocated buffer |
1767 // Print stack trace element to resource allocated buffer |
1763 static void print_stack_element_to_stream(outputStream* st, Handle mirror, int method_id, |
1768 static void print_stack_element_to_stream(outputStream* st, Handle mirror, int method_id, |
1764 int version, int bci, int cpref) { |
1769 int version, int bci, Symbol* name) { |
1765 ResourceMark rm; |
1770 ResourceMark rm; |
1766 |
1771 |
1767 // Get strings and string lengths |
1772 // Get strings and string lengths |
1768 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
1773 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
1769 const char* klass_name = holder->external_name(); |
1774 const char* klass_name = holder->external_name(); |
1770 int buf_len = (int)strlen(klass_name); |
1775 int buf_len = (int)strlen(klass_name); |
1771 |
1776 |
1772 Method* method = holder->method_with_orig_idnum(method_id, version); |
1777 char* method_name = name->as_C_string(); |
1773 |
|
1774 // The method can be NULL if the requested class version is gone |
|
1775 Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref); |
|
1776 char* method_name = sym->as_C_string(); |
|
1777 buf_len += (int)strlen(method_name); |
1778 buf_len += (int)strlen(method_name); |
1778 |
1779 |
1779 char* source_file_name = NULL; |
1780 char* source_file_name = NULL; |
1780 Symbol* source = Backtrace::get_source_file_name(holder, version); |
1781 Symbol* source = Backtrace::get_source_file_name(holder, version); |
1781 if (source != NULL) { |
1782 if (source != NULL) { |
1807 } else { |
1808 } else { |
1808 sprintf(buf + (int)strlen(buf), "%s/", module_name); |
1809 sprintf(buf + (int)strlen(buf), "%s/", module_name); |
1809 } |
1810 } |
1810 } |
1811 } |
1811 |
1812 |
|
1813 // The method can be NULL if the requested class version is gone |
|
1814 Method* method = holder->method_with_orig_idnum(method_id, version); |
1812 if (!version_matches(method, version)) { |
1815 if (!version_matches(method, version)) { |
1813 strcat(buf, "Redefined)"); |
1816 strcat(buf, "Redefined)"); |
1814 } else { |
1817 } else { |
1815 int line_number = Backtrace::get_line_number(method, bci); |
1818 int line_number = Backtrace::get_line_number(method, bci); |
1816 if (line_number == -2) { |
1819 if (line_number == -2) { |
1838 |
1841 |
1839 void java_lang_Throwable::print_stack_element(outputStream *st, const methodHandle& method, int bci) { |
1842 void java_lang_Throwable::print_stack_element(outputStream *st, const methodHandle& method, int bci) { |
1840 Handle mirror = method->method_holder()->java_mirror(); |
1843 Handle mirror = method->method_holder()->java_mirror(); |
1841 int method_id = method->orig_method_idnum(); |
1844 int method_id = method->orig_method_idnum(); |
1842 int version = method->constants()->version(); |
1845 int version = method->constants()->version(); |
1843 int cpref = method->name_index(); |
1846 print_stack_element_to_stream(st, mirror, method_id, version, bci, method->name()); |
1844 print_stack_element_to_stream(st, mirror, method_id, version, bci, cpref); |
|
1845 } |
1847 } |
1846 |
1848 |
1847 /** |
1849 /** |
1848 * Print the throwable message and its stack trace plus all causes by walking the |
1850 * Print the throwable message and its stack trace plus all causes by walking the |
1849 * cause chain. The output looks the same as of Throwable.printStackTrace(). |
1851 * cause chain. The output looks the same as of Throwable.printStackTrace(). |
1863 } |
1865 } |
1864 BacktraceIterator iter(result, THREAD); |
1866 BacktraceIterator iter(result, THREAD); |
1865 |
1867 |
1866 while (iter.repeat()) { |
1868 while (iter.repeat()) { |
1867 BacktraceElement bte = iter.next(THREAD); |
1869 BacktraceElement bte = iter.next(THREAD); |
1868 print_stack_element_to_stream(st, bte._mirror, bte._method_id, bte._version, bte._bci, bte._cpref); |
1870 print_stack_element_to_stream(st, bte._mirror, bte._method_id, bte._version, bte._bci, bte._name); |
1869 } |
1871 } |
1870 { |
1872 { |
1871 // Call getCause() which doesn't necessarily return the _cause field. |
1873 // Call getCause() which doesn't necessarily return the _cause field. |
1872 EXCEPTION_MARK; |
1874 EXCEPTION_MARK; |
1873 JavaValue cause(T_OBJECT); |
1875 JavaValue cause(T_OBJECT); |
2157 ik->initialize(CHECK_0); |
2159 ik->initialize(CHECK_0); |
2158 } |
2160 } |
2159 |
2161 |
2160 Handle element = ik->allocate_instance_handle(CHECK_0); |
2162 Handle element = ik->allocate_instance_handle(CHECK_0); |
2161 |
2163 |
2162 int cpref = method->name_index(); |
|
2163 int version = method->constants()->version(); |
2164 int version = method->constants()->version(); |
2164 fill_in(element, method->method_holder(), method, version, bci, cpref, CHECK_0); |
2165 fill_in(element, method->method_holder(), method, version, bci, method->name(), CHECK_0); |
2165 return element(); |
2166 return element(); |
2166 } |
2167 } |
2167 |
2168 |
2168 void java_lang_StackTraceElement::fill_in(Handle element, |
2169 void java_lang_StackTraceElement::fill_in(Handle element, |
2169 InstanceKlass* holder, const methodHandle& method, |
2170 InstanceKlass* holder, const methodHandle& method, |
2170 int version, int bci, int cpref, TRAPS) { |
2171 int version, int bci, Symbol* name, TRAPS) { |
2171 assert(element->is_a(SystemDictionary::StackTraceElement_klass()), "sanity check"); |
2172 assert(element->is_a(SystemDictionary::StackTraceElement_klass()), "sanity check"); |
2172 |
2173 |
2173 // Fill in class name |
2174 // Fill in class name |
2174 ResourceMark rm(THREAD); |
2175 ResourceMark rm(THREAD); |
2175 const char* str = holder->external_name(); |
2176 const char* str = holder->external_name(); |
2182 oop loader_name = java_lang_ClassLoader::name(loader); |
2183 oop loader_name = java_lang_ClassLoader::name(loader); |
2183 if (loader_name != NULL) |
2184 if (loader_name != NULL) |
2184 java_lang_StackTraceElement::set_classLoaderName(element(), loader_name); |
2185 java_lang_StackTraceElement::set_classLoaderName(element(), loader_name); |
2185 } |
2186 } |
2186 |
2187 |
2187 // The method can be NULL if the requested class version is gone |
|
2188 Symbol* sym = !method.is_null() ? method->name() : holder->constants()->symbol_at(cpref); |
|
2189 |
|
2190 // Fill in method name |
2188 // Fill in method name |
2191 oop methodname = StringTable::intern(sym, CHECK); |
2189 oop methodname = StringTable::intern(name, CHECK); |
2192 java_lang_StackTraceElement::set_methodName(element(), methodname); |
2190 java_lang_StackTraceElement::set_methodName(element(), methodname); |
2193 |
2191 |
2194 // Fill in module name and version |
2192 // Fill in module name and version |
2195 ModuleEntry* module = holder->module(); |
2193 ModuleEntry* module = holder->module(); |
2196 if (module->is_named()) { |
2194 if (module->is_named()) { |
2203 module_version = NULL; |
2201 module_version = NULL; |
2204 } |
2202 } |
2205 java_lang_StackTraceElement::set_moduleVersion(element(), module_version); |
2203 java_lang_StackTraceElement::set_moduleVersion(element(), module_version); |
2206 } |
2204 } |
2207 |
2205 |
2208 if (!version_matches(method(), version)) { |
2206 if (method() == NULL || !version_matches(method(), version)) { |
2209 // The method was redefined, accurate line number information isn't available |
2207 // The method was redefined, accurate line number information isn't available |
2210 java_lang_StackTraceElement::set_fileName(element(), NULL); |
2208 java_lang_StackTraceElement::set_fileName(element(), NULL); |
2211 java_lang_StackTraceElement::set_lineNumber(element(), -1); |
2209 java_lang_StackTraceElement::set_lineNumber(element(), -1); |
2212 } else { |
2210 } else { |
2213 // Fill in source file name and line number. |
2211 // Fill in source file name and line number. |
2250 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k())); |
2248 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k())); |
2251 Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK); |
2249 Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK); |
2252 |
2250 |
2253 short version = stackFrame->short_field(_version_offset); |
2251 short version = stackFrame->short_field(_version_offset); |
2254 short bci = stackFrame->short_field(_bci_offset); |
2252 short bci = stackFrame->short_field(_bci_offset); |
2255 int cpref = method->name_index(); |
2253 Symbol* name = method->name(); |
2256 java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, cpref, CHECK); |
2254 java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, name, CHECK); |
2257 } |
2255 } |
2258 |
2256 |
2259 void java_lang_StackFrameInfo::compute_offsets() { |
2257 void java_lang_StackFrameInfo::compute_offsets() { |
2260 Klass* k = SystemDictionary::StackFrameInfo_klass(); |
2258 Klass* k = SystemDictionary::StackFrameInfo_klass(); |
2261 compute_offset(_declaringClass_offset, k, vmSymbols::declaringClass_name(), vmSymbols::class_signature()); |
2259 compute_offset(_declaringClass_offset, k, vmSymbols::declaringClass_name(), vmSymbols::class_signature()); |