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