mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
7174978: NPG: Fix bactrace builder for class redefinition
Remove Method* from backtrace but save version so redefine classes doesn't give inaccurate line numbers. Removed old Merlin API with duplicate code. Reviewed-by: dholmes, sspitsyn
This commit is contained in:
parent
68f3dd76c9
commit
e508ba9b0b
12 changed files with 297 additions and 341 deletions
|
@ -3,7 +3,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -205,7 +205,6 @@ SUNWprivate_1.1 {
|
|||
JVM_NewMultiArray;
|
||||
JVM_OnExit;
|
||||
JVM_Open;
|
||||
JVM_PrintStackTrace;
|
||||
JVM_RaiseSignal;
|
||||
JVM_RawMonitorCreate;
|
||||
JVM_RawMonitorDestroy;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -205,7 +205,6 @@ SUNWprivate_1.1 {
|
|||
JVM_NewMultiArray;
|
||||
JVM_OnExit;
|
||||
JVM_Open;
|
||||
JVM_PrintStackTrace;
|
||||
JVM_RaiseSignal;
|
||||
JVM_RawMonitorCreate;
|
||||
JVM_RawMonitorDestroy;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -201,7 +201,6 @@ SUNWprivate_1.1 {
|
|||
JVM_NewMultiArray;
|
||||
JVM_OnExit;
|
||||
JVM_Open;
|
||||
JVM_PrintStackTrace;
|
||||
JVM_RaiseSignal;
|
||||
JVM_RawMonitorCreate;
|
||||
JVM_RawMonitorDestroy;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -201,7 +201,6 @@ SUNWprivate_1.1 {
|
|||
JVM_NewMultiArray;
|
||||
JVM_OnExit;
|
||||
JVM_Open;
|
||||
JVM_PrintStackTrace;
|
||||
JVM_RaiseSignal;
|
||||
JVM_RawMonitorCreate;
|
||||
JVM_RawMonitorDestroy;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -201,7 +201,6 @@ SUNWprivate_1.1 {
|
|||
JVM_NewMultiArray;
|
||||
JVM_OnExit;
|
||||
JVM_Open;
|
||||
JVM_PrintStackTrace;
|
||||
JVM_RaiseSignal;
|
||||
JVM_RawMonitorCreate;
|
||||
JVM_RawMonitorDestroy;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1158,179 +1158,43 @@ void java_lang_Throwable::print(Handle throwable, outputStream* st) {
|
|||
}
|
||||
}
|
||||
|
||||
// Print stack trace element to resource allocated buffer
|
||||
char* java_lang_Throwable::print_stack_element_to_buffer(Method* method, int bci) {
|
||||
// Get strings and string lengths
|
||||
InstanceKlass* klass = method->method_holder();
|
||||
const char* klass_name = klass->external_name();
|
||||
int buf_len = (int)strlen(klass_name);
|
||||
char* source_file_name;
|
||||
if (klass->source_file_name() == NULL) {
|
||||
source_file_name = NULL;
|
||||
} else {
|
||||
source_file_name = klass->source_file_name()->as_C_string();
|
||||
buf_len += (int)strlen(source_file_name);
|
||||
}
|
||||
char* method_name = method->name()->as_C_string();
|
||||
buf_len += (int)strlen(method_name);
|
||||
// After this many redefines, the stack trace is unreliable.
|
||||
const int MAX_VERSION = USHRT_MAX;
|
||||
|
||||
// Allocate temporary buffer with extra space for formatting and line number
|
||||
char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64);
|
||||
// Helper backtrace functions to store bci|version together.
|
||||
static inline int merge_bci_and_version(int bci, int version) {
|
||||
// only store u2 for version, checking for overflow.
|
||||
if (version > USHRT_MAX || version < 0) version = MAX_VERSION;
|
||||
assert((jushort)bci == bci, "bci should be short");
|
||||
return build_int_from_shorts(version, bci);
|
||||
}
|
||||
|
||||
// Print stack trace line in buffer
|
||||
sprintf(buf, "\tat %s.%s", klass_name, method_name);
|
||||
static inline int bci_at(unsigned int merged) {
|
||||
return extract_high_short_from_int(merged);
|
||||
}
|
||||
static inline int version_at(unsigned int merged) {
|
||||
return extract_low_short_from_int(merged);
|
||||
}
|
||||
|
||||
static inline bool version_matches(Method* method, int version) {
|
||||
return (method->constants()->version() == version && version < MAX_VERSION);
|
||||
}
|
||||
|
||||
static inline int get_line_number(Method* method, int bci) {
|
||||
int line_number = 0;
|
||||
if (method->is_native()) {
|
||||
strcat(buf, "(Native Method)");
|
||||
// Negative value different from -1 below, enabling Java code in
|
||||
// class java.lang.StackTraceElement to distinguish "native" from
|
||||
// "no LineNumberTable". JDK tests for -2.
|
||||
line_number = -2;
|
||||
} else {
|
||||
int line_number = method->line_number_from_bci(bci);
|
||||
if (source_file_name != NULL && (line_number != -1)) {
|
||||
// Sourcename and linenumber
|
||||
sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number);
|
||||
} else if (source_file_name != NULL) {
|
||||
// Just sourcename
|
||||
sprintf(buf + (int)strlen(buf), "(%s)", source_file_name);
|
||||
} else {
|
||||
// Neither soucename and linenumber
|
||||
sprintf(buf + (int)strlen(buf), "(Unknown Source)");
|
||||
}
|
||||
nmethod* nm = method->code();
|
||||
if (WizardMode && nm != NULL) {
|
||||
sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm);
|
||||
// Returns -1 if no LineNumberTable, and otherwise actual line number
|
||||
line_number = method->line_number_from_bci(bci);
|
||||
if (line_number == -1 && ShowHiddenFrames) {
|
||||
line_number = bci + 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void java_lang_Throwable::print_stack_element(Handle stream, Method* method, int bci) {
|
||||
ResourceMark rm;
|
||||
char* buf = print_stack_element_to_buffer(method, bci);
|
||||
print_to_stream(stream, buf);
|
||||
}
|
||||
|
||||
void java_lang_Throwable::print_stack_element(outputStream *st, Method* method, int bci) {
|
||||
ResourceMark rm;
|
||||
char* buf = print_stack_element_to_buffer(method, bci);
|
||||
st->print_cr("%s", buf);
|
||||
}
|
||||
|
||||
void java_lang_Throwable::print_to_stream(Handle stream, const char* str) {
|
||||
if (stream.is_null()) {
|
||||
tty->print_cr("%s", str);
|
||||
} else {
|
||||
EXCEPTION_MARK;
|
||||
JavaValue result(T_VOID);
|
||||
Handle arg (THREAD, oopFactory::new_charArray(str, THREAD));
|
||||
if (!HAS_PENDING_EXCEPTION) {
|
||||
JavaCalls::call_virtual(&result,
|
||||
stream,
|
||||
KlassHandle(THREAD, stream->klass()),
|
||||
vmSymbols::println_name(),
|
||||
vmSymbols::char_array_void_signature(),
|
||||
arg,
|
||||
THREAD);
|
||||
}
|
||||
// Ignore any exceptions. we are in the middle of exception handling. Same as classic VM.
|
||||
if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const char* java_lang_Throwable::no_stack_trace_message() {
|
||||
return "\t<<no stack trace available>>";
|
||||
}
|
||||
|
||||
|
||||
// Currently used only for exceptions occurring during startup
|
||||
void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) {
|
||||
Thread *THREAD = Thread::current();
|
||||
Handle h_throwable(THREAD, throwable);
|
||||
while (h_throwable.not_null()) {
|
||||
objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable())));
|
||||
if (result.is_null()) {
|
||||
st->print_cr(no_stack_trace_message());
|
||||
return;
|
||||
}
|
||||
|
||||
while (result.not_null()) {
|
||||
typeArrayHandle methods (THREAD,
|
||||
typeArrayOop(result->obj_at(trace_methods_offset)));
|
||||
typeArrayHandle bcis (THREAD,
|
||||
typeArrayOop(result->obj_at(trace_bcis_offset)));
|
||||
|
||||
if (methods.is_null() || bcis.is_null()) {
|
||||
st->print_cr(no_stack_trace_message());
|
||||
return;
|
||||
}
|
||||
|
||||
int length = methods()->length();
|
||||
for (int index = 0; index < length; index++) {
|
||||
Method* method = ((Method*)methods()->metadata_at(index));
|
||||
if (method == NULL) goto handle_cause;
|
||||
int bci = bcis->ushort_at(index);
|
||||
print_stack_element(st, method, bci);
|
||||
}
|
||||
result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset)));
|
||||
}
|
||||
handle_cause:
|
||||
{
|
||||
EXCEPTION_MARK;
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_virtual(&result,
|
||||
h_throwable,
|
||||
KlassHandle(THREAD, h_throwable->klass()),
|
||||
vmSymbols::getCause_name(),
|
||||
vmSymbols::void_throwable_signature(),
|
||||
THREAD);
|
||||
// Ignore any exceptions. we are in the middle of exception handling. Same as classic VM.
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
h_throwable = Handle();
|
||||
} else {
|
||||
h_throwable = Handle(THREAD, (oop) result.get_jobject());
|
||||
if (h_throwable.not_null()) {
|
||||
st->print("Caused by: ");
|
||||
print(h_throwable, st);
|
||||
st->cr();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void java_lang_Throwable::print_stack_trace(oop throwable, oop print_stream) {
|
||||
// Note: this is no longer used in Merlin, but we support it for compatibility.
|
||||
Thread *thread = Thread::current();
|
||||
Handle stream(thread, print_stream);
|
||||
objArrayHandle result (thread, objArrayOop(backtrace(throwable)));
|
||||
if (result.is_null()) {
|
||||
print_to_stream(stream, no_stack_trace_message());
|
||||
return;
|
||||
}
|
||||
|
||||
while (result.not_null()) {
|
||||
typeArrayHandle methods(thread,
|
||||
typeArrayOop(result->obj_at(trace_methods_offset)));
|
||||
typeArrayHandle bcis (thread,
|
||||
typeArrayOop(result->obj_at(trace_bcis_offset)));
|
||||
|
||||
if (methods.is_null() || bcis.is_null()) {
|
||||
print_to_stream(stream, no_stack_trace_message());
|
||||
return;
|
||||
}
|
||||
|
||||
int length = methods()->length();
|
||||
for (int index = 0; index < length; index++) {
|
||||
Method* method = ((Method*)methods()->metadata_at(index));
|
||||
if (method == NULL) return;
|
||||
int bci = bcis->ushort_at(index);
|
||||
print_stack_element(stream, method, bci);
|
||||
}
|
||||
result = objArrayHandle(thread, objArrayOop(result->obj_at(trace_next_offset)));
|
||||
}
|
||||
return line_number;
|
||||
}
|
||||
|
||||
// This class provides a simple wrapper over the internal structure of
|
||||
|
@ -1350,13 +1214,30 @@ class BacktraceBuilder: public StackObj {
|
|||
|
||||
enum {
|
||||
trace_methods_offset = java_lang_Throwable::trace_methods_offset,
|
||||
trace_bcis_offset = java_lang_Throwable::trace_bcis_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
|
||||
};
|
||||
|
||||
// get info out of chunks
|
||||
static typeArrayOop get_methods(objArrayHandle chunk) {
|
||||
typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset));
|
||||
assert(methods != NULL, "method array should be initialized in backtrace");
|
||||
return methods;
|
||||
}
|
||||
static typeArrayOop get_bcis(objArrayHandle chunk) {
|
||||
typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset));
|
||||
assert(bcis != NULL, "bci array should be initialized in backtrace");
|
||||
return bcis;
|
||||
}
|
||||
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(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL) {
|
||||
expand(CHECK);
|
||||
|
@ -1364,6 +1245,19 @@ class BacktraceBuilder: public StackObj {
|
|||
_index = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void expand(TRAPS) {
|
||||
objArrayHandle old_head(THREAD, _head);
|
||||
Pause_No_Safepoint_Verifier pnsv(&_nsv);
|
||||
|
@ -1371,10 +1265,10 @@ class BacktraceBuilder: public StackObj {
|
|||
objArrayOop head = oopFactory::new_objectArray(trace_size, CHECK);
|
||||
objArrayHandle new_head(THREAD, head);
|
||||
|
||||
typeArrayOop methods = oopFactory::new_metaDataArray(trace_chunk_size, CHECK);
|
||||
typeArrayOop methods = oopFactory::new_shortArray(trace_chunk_size, CHECK);
|
||||
typeArrayHandle new_methods(THREAD, methods);
|
||||
|
||||
typeArrayOop bcis = oopFactory::new_shortArray(trace_chunk_size, CHECK);
|
||||
typeArrayOop bcis = oopFactory::new_intArray(trace_chunk_size, CHECK);
|
||||
typeArrayHandle new_bcis(THREAD, bcis);
|
||||
|
||||
objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK);
|
||||
|
@ -1389,7 +1283,7 @@ class BacktraceBuilder: public StackObj {
|
|||
|
||||
_head = new_head();
|
||||
_methods = new_methods();
|
||||
_bcis = new_bcis();
|
||||
_bcis = new_bcis();
|
||||
_mirrors = new_mirrors();
|
||||
_index = 0;
|
||||
}
|
||||
|
@ -1403,7 +1297,6 @@ class BacktraceBuilder: public StackObj {
|
|||
// shorts. The later line number lookup would just smear the -1
|
||||
// to a 0 even if it could be recorded.
|
||||
if (bci == SynchronizationEntryBCI) bci = 0;
|
||||
assert(bci == (jushort)bci, "doesn't fit");
|
||||
|
||||
if (_index >= trace_chunk_size) {
|
||||
methodHandle mhandle(THREAD, method);
|
||||
|
@ -1411,26 +1304,148 @@ class BacktraceBuilder: public StackObj {
|
|||
method = mhandle();
|
||||
}
|
||||
|
||||
_methods->metadata_at_put(_index, method);
|
||||
_bcis->ushort_at_put(_index, bci);
|
||||
// we need to save the mirrors in the backtrace to keep the methods from
|
||||
// being unloaded if their class loader is unloaded while we still have
|
||||
// this stack trace.
|
||||
_methods->short_at_put(_index, method->method_idnum());
|
||||
_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());
|
||||
_index++;
|
||||
}
|
||||
|
||||
Method* current_method() {
|
||||
assert(_index >= 0 && _index < trace_chunk_size, "out of range");
|
||||
return ((Method*)_methods->metadata_at(_index));
|
||||
}
|
||||
|
||||
jushort current_bci() {
|
||||
assert(_index >= 0 && _index < trace_chunk_size, "out of range");
|
||||
return _bcis->ushort_at(_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) {
|
||||
|
||||
// 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);
|
||||
|
||||
// pushing to the stack trace added one.
|
||||
Method* method = holder->method_with_idnum(method_id);
|
||||
char* method_name = method->name()->as_C_string();
|
||||
buf_len += (int)strlen(method_name);
|
||||
|
||||
char* source_file_name = NULL;
|
||||
if (version_matches(method, version)) {
|
||||
Symbol* source = holder->source_file_name();
|
||||
if (source != NULL) {
|
||||
source_file_name = source->as_C_string();
|
||||
buf_len += (int)strlen(source_file_name);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate temporary buffer with extra space for formatting and line number
|
||||
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)) {
|
||||
// Sourcename and linenumber
|
||||
sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number);
|
||||
} else if (source_file_name != NULL) {
|
||||
// Just sourcename
|
||||
sprintf(buf + (int)strlen(buf), "(%s)", source_file_name);
|
||||
} else {
|
||||
// Neither sourcename nor linenumber
|
||||
sprintf(buf + (int)strlen(buf), "(Unknown Source)");
|
||||
}
|
||||
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) {
|
||||
ResourceMark rm;
|
||||
char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci);
|
||||
st->print_cr("%s", buf);
|
||||
}
|
||||
|
||||
void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) {
|
||||
Handle mirror = method->method_holder()->java_mirror();
|
||||
int method_id = method->method_idnum();
|
||||
int version = method->constants()->version();
|
||||
print_stack_element(st, mirror, method_id, version, bci);
|
||||
}
|
||||
|
||||
const char* java_lang_Throwable::no_stack_trace_message() {
|
||||
return "\t<<no stack trace available>>";
|
||||
}
|
||||
|
||||
|
||||
// Currently used only for exceptions occurring during startup
|
||||
void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) {
|
||||
Thread *THREAD = Thread::current();
|
||||
Handle h_throwable(THREAD, throwable);
|
||||
while (h_throwable.not_null()) {
|
||||
objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable())));
|
||||
if (result.is_null()) {
|
||||
st->print_cr(no_stack_trace_message());
|
||||
return;
|
||||
}
|
||||
|
||||
while (result.not_null()) {
|
||||
|
||||
// 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;
|
||||
int method = methods->short_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:
|
||||
{
|
||||
EXCEPTION_MARK;
|
||||
JavaValue cause(T_OBJECT);
|
||||
JavaCalls::call_virtual(&cause,
|
||||
h_throwable,
|
||||
KlassHandle(THREAD, h_throwable->klass()),
|
||||
vmSymbols::getCause_name(),
|
||||
vmSymbols::void_throwable_signature(),
|
||||
THREAD);
|
||||
// Ignore any exceptions. we are in the middle of exception handling. Same as classic VM.
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
h_throwable = Handle();
|
||||
} else {
|
||||
h_throwable = Handle(THREAD, (oop) cause.get_jobject());
|
||||
if (h_throwable.not_null()) {
|
||||
st->print("Caused by: ");
|
||||
print(h_throwable, st);
|
||||
st->cr();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS) {
|
||||
if (!StackTraceInThrowable) return;
|
||||
|
@ -1591,21 +1606,8 @@ void java_lang_Throwable::allocate_backtrace(Handle throwable, TRAPS) {
|
|||
|
||||
// No-op if stack trace is disabled
|
||||
if (!StackTraceInThrowable) return;
|
||||
|
||||
objArrayOop h_oop = oopFactory::new_objectArray(trace_size, CHECK);
|
||||
objArrayHandle backtrace (THREAD, h_oop);
|
||||
typeArrayOop m_oop = oopFactory::new_metaDataArray(trace_chunk_size, CHECK);
|
||||
typeArrayHandle methods (THREAD, m_oop);
|
||||
typeArrayOop b = oopFactory::new_shortArray(trace_chunk_size, CHECK);
|
||||
typeArrayHandle bcis(THREAD, b);
|
||||
objArrayOop mirror_oop = oopFactory::new_objectArray(trace_chunk_size, CHECK);
|
||||
objArrayHandle mirrors (THREAD, mirror_oop);
|
||||
|
||||
// backtrace has space for one chunk (next is NULL)
|
||||
backtrace->obj_at_put(trace_methods_offset, methods());
|
||||
backtrace->obj_at_put(trace_bcis_offset, bcis());
|
||||
backtrace->obj_at_put(trace_mirrors_offset, mirrors());
|
||||
set_backtrace(throwable(), backtrace());
|
||||
BacktraceBuilder bt(CHECK); // creates a backtrace
|
||||
set_backtrace(throwable(), bt.backtrace());
|
||||
}
|
||||
|
||||
|
||||
|
@ -1617,48 +1619,26 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t
|
|||
|
||||
assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check");
|
||||
|
||||
objArrayOop backtrace = (objArrayOop)java_lang_Throwable::backtrace(throwable());
|
||||
assert(backtrace != NULL, "backtrace not preallocated");
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
|
||||
oop m = backtrace->obj_at(trace_methods_offset);
|
||||
typeArrayOop methods = typeArrayOop(m);
|
||||
assert(methods != NULL && methods->length() > 0, "method array not preallocated");
|
||||
objArrayHandle backtrace (THREAD, (objArrayOop)java_lang_Throwable::backtrace(throwable()));
|
||||
assert(backtrace.not_null(), "backtrace should have been preallocated");
|
||||
|
||||
oop b = backtrace->obj_at(trace_bcis_offset);
|
||||
typeArrayOop bcis = typeArrayOop(b);
|
||||
assert(bcis != NULL, "bci array not preallocated");
|
||||
ResourceMark rm(THREAD);
|
||||
vframeStream st(THREAD);
|
||||
|
||||
oop mr = backtrace->obj_at(trace_mirrors_offset);
|
||||
objArrayOop mirrors = objArrayOop(mr);
|
||||
assert(mirrors != NULL, "bci array not preallocated");
|
||||
|
||||
assert(methods->length() == bcis->length() &&
|
||||
methods->length() == mirrors->length(),
|
||||
"method and bci arrays should match");
|
||||
|
||||
JavaThread* thread = JavaThread::current();
|
||||
ResourceMark rm(thread);
|
||||
vframeStream st(thread);
|
||||
BacktraceBuilder bt(backtrace);
|
||||
|
||||
// Unlike fill_in_stack_trace we do not skip fillInStackTrace or throwable init
|
||||
// methods as preallocated errors aren't created by "java" code.
|
||||
|
||||
// fill in as much stack trace as possible
|
||||
typeArrayOop methods = BacktraceBuilder::get_methods(backtrace);
|
||||
int max_chunks = MIN2(methods->length(), (int)MaxJavaStackTraceDepth);
|
||||
int chunk_count = 0;
|
||||
|
||||
for (;!st.at_end(); st.next()) {
|
||||
// Add entry and smear the -1 bci to 0 since the array only holds
|
||||
// unsigned shorts. The later line number lookup would just smear
|
||||
// the -1 to a 0 even if it could be recorded.
|
||||
int bci = st.bci();
|
||||
if (bci == SynchronizationEntryBCI) bci = 0;
|
||||
assert(bci == (jushort)bci, "doesn't fit");
|
||||
bcis->ushort_at_put(chunk_count, bci);
|
||||
methods->metadata_at_put(chunk_count, st.method());
|
||||
mirrors->obj_at_put(chunk_count,
|
||||
st.method()->method_holder()->java_mirror());
|
||||
|
||||
bt.push(st.method(), st.bci(), CHECK);
|
||||
chunk_count++;
|
||||
|
||||
// Bail-out for deep stacks
|
||||
|
@ -1672,7 +1652,6 @@ void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle t
|
|||
java_lang_Throwable::set_stacktrace(throwable(), java_lang_Throwable::unassigned_stacktrace());
|
||||
assert(java_lang_Throwable::unassigned_stacktrace() != NULL, "not initialized");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1691,12 +1670,12 @@ int java_lang_Throwable::get_stack_trace_depth(oop throwable, TRAPS) {
|
|||
chunk = next;
|
||||
}
|
||||
assert(chunk != NULL && chunk->obj_at(trace_next_offset) == NULL, "sanity check");
|
||||
// Count element in remaining partial chunk
|
||||
typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset));
|
||||
typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset));
|
||||
assert(methods != NULL && bcis != NULL, "sanity check");
|
||||
for (int i = 0; i < methods->length(); i++) {
|
||||
if (methods->metadata_at(i) == NULL) break;
|
||||
// Count element in remaining partial chunk. NULL value for mirror
|
||||
// marks the end of the stack trace elements that are saved.
|
||||
objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk);
|
||||
assert(mirrors != NULL, "sanity check");
|
||||
for (int i = 0; i < mirrors->length(); i++) {
|
||||
if (mirrors->obj_at(i) == NULL) break;
|
||||
depth++;
|
||||
}
|
||||
}
|
||||
|
@ -1722,25 +1701,28 @@ oop java_lang_Throwable::get_stack_trace_element(oop throwable, int index, TRAPS
|
|||
if (chunk == NULL) {
|
||||
THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL);
|
||||
}
|
||||
// Get method,bci from chunk
|
||||
typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset));
|
||||
typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset));
|
||||
assert(methods != NULL && bcis != NULL, "sanity check");
|
||||
methodHandle method(THREAD, ((Method*)methods->metadata_at(chunk_index)));
|
||||
int bci = bcis->ushort_at(chunk_index);
|
||||
// Get method id, bci, version and 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");
|
||||
|
||||
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));
|
||||
Handle mirror(THREAD, mirrors->obj_at(chunk_index));
|
||||
|
||||
// Chunk can be partial full
|
||||
if (method.is_null()) {
|
||||
if (mirror.is_null()) {
|
||||
THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL);
|
||||
}
|
||||
|
||||
oop element = java_lang_StackTraceElement::create(method, bci, CHECK_0);
|
||||
oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, CHECK_0);
|
||||
return element;
|
||||
}
|
||||
|
||||
oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
|
||||
// SystemDictionary::stackTraceElement_klass() will be null for pre-1.4 JDKs
|
||||
assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4");
|
||||
|
||||
oop java_lang_StackTraceElement::create(Handle mirror, int method_id, int version, int bci, TRAPS) {
|
||||
// Allocate java.lang.StackTraceElement instance
|
||||
Klass* k = SystemDictionary::StackTraceElement_klass();
|
||||
assert(k != NULL, "must be loaded in 1.4+");
|
||||
|
@ -1752,37 +1734,39 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
|
|||
Handle element = ik->allocate_instance_handle(CHECK_0);
|
||||
// Fill in class name
|
||||
ResourceMark rm(THREAD);
|
||||
const char* str = method->method_holder()->external_name();
|
||||
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
|
||||
Method* method = holder->method_with_idnum(method_id);
|
||||
oop methodname = StringTable::intern(method->name(), CHECK_0);
|
||||
java_lang_StackTraceElement::set_methodName(element(), methodname);
|
||||
// Fill in source file name
|
||||
Symbol* source = method->method_holder()->source_file_name();
|
||||
if (ShowHiddenFrames && source == NULL)
|
||||
source = vmSymbols::unknown_class_name();
|
||||
oop filename = StringTable::intern(source, CHECK_0);
|
||||
java_lang_StackTraceElement::set_fileName(element(), filename);
|
||||
// File in source line number
|
||||
int line_number;
|
||||
if (method->is_native()) {
|
||||
// Negative value different from -1 below, enabling Java code in
|
||||
// class java.lang.StackTraceElement to distinguish "native" from
|
||||
// "no LineNumberTable".
|
||||
line_number = -2;
|
||||
} else {
|
||||
// Returns -1 if no LineNumberTable, and otherwise actual line number
|
||||
line_number = method->line_number_from_bci(bci);
|
||||
if (line_number == -1 && ShowHiddenFrames) {
|
||||
line_number = bci + 1000000;
|
||||
}
|
||||
}
|
||||
java_lang_StackTraceElement::set_lineNumber(element(), line_number);
|
||||
|
||||
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 = holder->source_file_name();
|
||||
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(methodHandle method, int bci, TRAPS) {
|
||||
Handle mirror (THREAD, method->method_holder()->java_mirror());
|
||||
int method_id = method->method_idnum();
|
||||
return create(mirror, method_id, method->constants()->version(), bci, THREAD);
|
||||
}
|
||||
|
||||
void java_lang_reflect_AccessibleObject::compute_offsets() {
|
||||
Klass* k = SystemDictionary::reflect_AccessibleObject_klass();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -469,8 +469,7 @@ class java_lang_Throwable: AllStatic {
|
|||
static int static_unassigned_stacktrace_offset;
|
||||
|
||||
// Printing
|
||||
static char* print_stack_element_to_buffer(Method* method, int bci);
|
||||
static void print_to_stream(Handle stream, const char* str);
|
||||
static char* print_stack_element_to_buffer(Handle mirror, int method, int version, int bci);
|
||||
// StackTrace (programmatic access, new since 1.4)
|
||||
static void clear_stacktrace(oop throwable);
|
||||
// No stack trace available
|
||||
|
@ -490,12 +489,9 @@ class java_lang_Throwable: AllStatic {
|
|||
static oop message(oop throwable);
|
||||
static oop message(Handle throwable);
|
||||
static void set_message(oop throwable, oop value);
|
||||
// Print stack trace stored in exception by call-back to Java
|
||||
// Note: this is no longer used in Merlin, but we still suppport
|
||||
// it for compatibility.
|
||||
static void print_stack_trace(oop throwable, oop print_stream);
|
||||
static void print_stack_element(Handle stream, Method* method, int bci);
|
||||
static void print_stack_element(outputStream *st, Method* method, int bci);
|
||||
static void print_stack_element(outputStream *st, Handle mirror, int method,
|
||||
int version, int bci);
|
||||
static void print_stack_element(outputStream *st, methodHandle method, int bci);
|
||||
static void print_stack_usage(Handle stream);
|
||||
|
||||
// Allocate space for backtrace (created but stack trace not filled in)
|
||||
|
@ -1263,7 +1259,8 @@ class java_lang_StackTraceElement: AllStatic {
|
|||
static void set_lineNumber(oop element, int value);
|
||||
|
||||
// Create an instance of StackTraceElement
|
||||
static oop create(methodHandle m, int bci, TRAPS);
|
||||
static oop create(Handle mirror, int method, int version, int bci, TRAPS);
|
||||
static oop create(methodHandle method, int bci, TRAPS);
|
||||
|
||||
// Debugging
|
||||
friend class JavaClasses;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -66,7 +66,7 @@ ConstantPool::ConstantPool(Array<u1>* tags) {
|
|||
set_pool_holder(NULL);
|
||||
set_flags(0);
|
||||
// only set to non-zero if constant pool is merged by RedefineClasses
|
||||
set_orig_length(0);
|
||||
set_version(0);
|
||||
set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock"));
|
||||
// all fields are initialized; needed for GC
|
||||
set_on_stack(false);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -103,8 +103,8 @@ class ConstantPool : public Metadata {
|
|||
union {
|
||||
// set for CDS to restore resolved references
|
||||
int _resolved_reference_length;
|
||||
// only set to non-zero if constant pool is merged by RedefineClasses
|
||||
int _orig_length;
|
||||
// keeps version number for redefined classes (used in backtrace)
|
||||
int _version;
|
||||
} _saved;
|
||||
|
||||
Monitor* _lock;
|
||||
|
@ -784,8 +784,11 @@ class ConstantPool : public Metadata {
|
|||
static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS);
|
||||
static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS);
|
||||
int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS);
|
||||
int orig_length() const { return _saved._orig_length; }
|
||||
void set_orig_length(int orig_length) { _saved._orig_length = orig_length; }
|
||||
int version() const { return _saved._version; }
|
||||
void set_version(int version) { _saved._version = version; }
|
||||
void increment_and_save_version(int version) {
|
||||
_saved._version = version >= 0 ? version++ : version; // keep overflow
|
||||
}
|
||||
|
||||
void set_resolved_reference_length(int length) { _saved._resolved_reference_length = length; }
|
||||
int resolved_reference_length() const { return _saved._resolved_reference_length; }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -484,15 +484,6 @@ JVM_ENTRY(void, JVM_FillInStackTrace(JNIEnv *env, jobject receiver))
|
|||
JVM_END
|
||||
|
||||
|
||||
JVM_ENTRY(void, JVM_PrintStackTrace(JNIEnv *env, jobject receiver, jobject printable))
|
||||
JVMWrapper("JVM_PrintStackTrace");
|
||||
// Note: This is no longer used in Merlin, but we still support it for compatibility.
|
||||
oop exception = JNIHandles::resolve_non_null(receiver);
|
||||
oop stream = JNIHandles::resolve_non_null(printable);
|
||||
java_lang_Throwable::print_stack_trace(exception, stream);
|
||||
JVM_END
|
||||
|
||||
|
||||
JVM_ENTRY(jint, JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable))
|
||||
JVMWrapper("JVM_GetStackTraceDepth");
|
||||
oop exception = JNIHandles::resolve(throwable);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -212,9 +212,6 @@ JVM_IsNaN(jdouble d);
|
|||
JNIEXPORT void JNICALL
|
||||
JVM_FillInStackTrace(JNIEnv *env, jobject throwable);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JVM_PrintStackTrace(JNIEnv *env, jobject throwable, jobject printable);
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -1334,20 +1334,8 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite(
|
|||
return JVMTI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
int orig_length = old_cp->orig_length();
|
||||
if (orig_length == 0) {
|
||||
// This old_cp is an actual original constant pool. We save
|
||||
// the original length in the merged constant pool so that
|
||||
// merge_constant_pools() can be more efficient. If a constant
|
||||
// pool has a non-zero orig_length() value, then that constant
|
||||
// pool was created by a merge operation in RedefineClasses.
|
||||
merge_cp->set_orig_length(old_cp->length());
|
||||
} else {
|
||||
// This old_cp is a merged constant pool from a previous
|
||||
// RedefineClasses() calls so just copy the orig_length()
|
||||
// value.
|
||||
merge_cp->set_orig_length(old_cp->orig_length());
|
||||
}
|
||||
// Update the version number of the constant pool
|
||||
merge_cp->increment_and_save_version(old_cp->version());
|
||||
|
||||
ResourceMark rm(THREAD);
|
||||
_index_map_count = 0;
|
||||
|
@ -2417,18 +2405,19 @@ void VM_RedefineClasses::set_new_constant_pool(
|
|||
int scratch_cp_length, TRAPS) {
|
||||
assert(scratch_cp->length() >= scratch_cp_length, "sanity check");
|
||||
|
||||
// scratch_cp is a merged constant pool and has enough space for a
|
||||
// worst case merge situation. We want to associate the minimum
|
||||
// sized constant pool with the klass to save space.
|
||||
constantPoolHandle smaller_cp(THREAD,
|
||||
ConstantPool::allocate(loader_data, scratch_cp_length,
|
||||
THREAD));
|
||||
// preserve orig_length() value in the smaller copy
|
||||
int orig_length = scratch_cp->orig_length();
|
||||
assert(orig_length != 0, "sanity check");
|
||||
smaller_cp->set_orig_length(orig_length);
|
||||
scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD);
|
||||
scratch_cp = smaller_cp;
|
||||
// scratch_cp is a merged constant pool and has enough space for a
|
||||
// worst case merge situation. We want to associate the minimum
|
||||
// sized constant pool with the klass to save space.
|
||||
constantPoolHandle smaller_cp(THREAD,
|
||||
ConstantPool::allocate(loader_data, scratch_cp_length, THREAD));
|
||||
|
||||
// preserve version() value in the smaller copy
|
||||
int version = scratch_cp->version();
|
||||
assert(version != 0, "sanity check");
|
||||
smaller_cp->set_version(version);
|
||||
|
||||
scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD);
|
||||
scratch_cp = smaller_cp;
|
||||
|
||||
// attach new constant pool to klass
|
||||
scratch_cp->set_pool_holder(scratch_class());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue