1156 if (msg != NULL) { |
1156 if (msg != NULL) { |
1157 st->print(": %s", java_lang_String::as_utf8_string(msg)); |
1157 st->print(": %s", java_lang_String::as_utf8_string(msg)); |
1158 } |
1158 } |
1159 } |
1159 } |
1160 |
1160 |
1161 // Print stack trace element to resource allocated buffer |
1161 // After this many redefines, the stack trace is unreliable. |
1162 char* java_lang_Throwable::print_stack_element_to_buffer(Method* method, int bci) { |
1162 const int MAX_VERSION = USHRT_MAX; |
1163 // Get strings and string lengths |
1163 |
1164 InstanceKlass* klass = method->method_holder(); |
1164 // Helper backtrace functions to store bci|version together. |
1165 const char* klass_name = klass->external_name(); |
1165 static inline int merge_bci_and_version(int bci, int version) { |
1166 int buf_len = (int)strlen(klass_name); |
1166 // only store u2 for version, checking for overflow. |
1167 char* source_file_name; |
1167 if (version > USHRT_MAX || version < 0) version = MAX_VERSION; |
1168 if (klass->source_file_name() == NULL) { |
1168 assert((jushort)bci == bci, "bci should be short"); |
1169 source_file_name = NULL; |
1169 return build_int_from_shorts(version, bci); |
|
1170 } |
|
1171 |
|
1172 static inline int bci_at(unsigned int merged) { |
|
1173 return extract_high_short_from_int(merged); |
|
1174 } |
|
1175 static inline int version_at(unsigned int merged) { |
|
1176 return extract_low_short_from_int(merged); |
|
1177 } |
|
1178 |
|
1179 static inline bool version_matches(Method* method, int version) { |
|
1180 return (method->constants()->version() == version && version < MAX_VERSION); |
|
1181 } |
|
1182 |
|
1183 static inline int get_line_number(Method* method, int bci) { |
|
1184 int line_number = 0; |
|
1185 if (method->is_native()) { |
|
1186 // Negative value different from -1 below, enabling Java code in |
|
1187 // class java.lang.StackTraceElement to distinguish "native" from |
|
1188 // "no LineNumberTable". JDK tests for -2. |
|
1189 line_number = -2; |
1170 } else { |
1190 } else { |
1171 source_file_name = klass->source_file_name()->as_C_string(); |
1191 // Returns -1 if no LineNumberTable, and otherwise actual line number |
1172 buf_len += (int)strlen(source_file_name); |
1192 line_number = method->line_number_from_bci(bci); |
1173 } |
1193 if (line_number == -1 && ShowHiddenFrames) { |
1174 char* method_name = method->name()->as_C_string(); |
1194 line_number = bci + 1000000; |
1175 buf_len += (int)strlen(method_name); |
1195 } |
1176 |
1196 } |
1177 // Allocate temporary buffer with extra space for formatting and line number |
1197 return line_number; |
1178 char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); |
|
1179 |
|
1180 // Print stack trace line in buffer |
|
1181 sprintf(buf, "\tat %s.%s", klass_name, method_name); |
|
1182 if (method->is_native()) { |
|
1183 strcat(buf, "(Native Method)"); |
|
1184 } else { |
|
1185 int line_number = method->line_number_from_bci(bci); |
|
1186 if (source_file_name != NULL && (line_number != -1)) { |
|
1187 // Sourcename and linenumber |
|
1188 sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number); |
|
1189 } else if (source_file_name != NULL) { |
|
1190 // Just sourcename |
|
1191 sprintf(buf + (int)strlen(buf), "(%s)", source_file_name); |
|
1192 } else { |
|
1193 // Neither soucename and linenumber |
|
1194 sprintf(buf + (int)strlen(buf), "(Unknown Source)"); |
|
1195 } |
|
1196 nmethod* nm = method->code(); |
|
1197 if (WizardMode && nm != NULL) { |
|
1198 sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); |
|
1199 } |
|
1200 } |
|
1201 |
|
1202 return buf; |
|
1203 } |
|
1204 |
|
1205 |
|
1206 void java_lang_Throwable::print_stack_element(Handle stream, Method* method, int bci) { |
|
1207 ResourceMark rm; |
|
1208 char* buf = print_stack_element_to_buffer(method, bci); |
|
1209 print_to_stream(stream, buf); |
|
1210 } |
|
1211 |
|
1212 void java_lang_Throwable::print_stack_element(outputStream *st, Method* method, int bci) { |
|
1213 ResourceMark rm; |
|
1214 char* buf = print_stack_element_to_buffer(method, bci); |
|
1215 st->print_cr("%s", buf); |
|
1216 } |
|
1217 |
|
1218 void java_lang_Throwable::print_to_stream(Handle stream, const char* str) { |
|
1219 if (stream.is_null()) { |
|
1220 tty->print_cr("%s", str); |
|
1221 } else { |
|
1222 EXCEPTION_MARK; |
|
1223 JavaValue result(T_VOID); |
|
1224 Handle arg (THREAD, oopFactory::new_charArray(str, THREAD)); |
|
1225 if (!HAS_PENDING_EXCEPTION) { |
|
1226 JavaCalls::call_virtual(&result, |
|
1227 stream, |
|
1228 KlassHandle(THREAD, stream->klass()), |
|
1229 vmSymbols::println_name(), |
|
1230 vmSymbols::char_array_void_signature(), |
|
1231 arg, |
|
1232 THREAD); |
|
1233 } |
|
1234 // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. |
|
1235 if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION; |
|
1236 } |
|
1237 |
|
1238 } |
|
1239 |
|
1240 |
|
1241 const char* java_lang_Throwable::no_stack_trace_message() { |
|
1242 return "\t<<no stack trace available>>"; |
|
1243 } |
|
1244 |
|
1245 |
|
1246 // Currently used only for exceptions occurring during startup |
|
1247 void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) { |
|
1248 Thread *THREAD = Thread::current(); |
|
1249 Handle h_throwable(THREAD, throwable); |
|
1250 while (h_throwable.not_null()) { |
|
1251 objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable()))); |
|
1252 if (result.is_null()) { |
|
1253 st->print_cr(no_stack_trace_message()); |
|
1254 return; |
|
1255 } |
|
1256 |
|
1257 while (result.not_null()) { |
|
1258 typeArrayHandle methods (THREAD, |
|
1259 typeArrayOop(result->obj_at(trace_methods_offset))); |
|
1260 typeArrayHandle bcis (THREAD, |
|
1261 typeArrayOop(result->obj_at(trace_bcis_offset))); |
|
1262 |
|
1263 if (methods.is_null() || bcis.is_null()) { |
|
1264 st->print_cr(no_stack_trace_message()); |
|
1265 return; |
|
1266 } |
|
1267 |
|
1268 int length = methods()->length(); |
|
1269 for (int index = 0; index < length; index++) { |
|
1270 Method* method = ((Method*)methods()->metadata_at(index)); |
|
1271 if (method == NULL) goto handle_cause; |
|
1272 int bci = bcis->ushort_at(index); |
|
1273 print_stack_element(st, method, bci); |
|
1274 } |
|
1275 result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); |
|
1276 } |
|
1277 handle_cause: |
|
1278 { |
|
1279 EXCEPTION_MARK; |
|
1280 JavaValue result(T_OBJECT); |
|
1281 JavaCalls::call_virtual(&result, |
|
1282 h_throwable, |
|
1283 KlassHandle(THREAD, h_throwable->klass()), |
|
1284 vmSymbols::getCause_name(), |
|
1285 vmSymbols::void_throwable_signature(), |
|
1286 THREAD); |
|
1287 // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. |
|
1288 if (HAS_PENDING_EXCEPTION) { |
|
1289 CLEAR_PENDING_EXCEPTION; |
|
1290 h_throwable = Handle(); |
|
1291 } else { |
|
1292 h_throwable = Handle(THREAD, (oop) result.get_jobject()); |
|
1293 if (h_throwable.not_null()) { |
|
1294 st->print("Caused by: "); |
|
1295 print(h_throwable, st); |
|
1296 st->cr(); |
|
1297 } |
|
1298 } |
|
1299 } |
|
1300 } |
|
1301 } |
|
1302 |
|
1303 |
|
1304 void java_lang_Throwable::print_stack_trace(oop throwable, oop print_stream) { |
|
1305 // Note: this is no longer used in Merlin, but we support it for compatibility. |
|
1306 Thread *thread = Thread::current(); |
|
1307 Handle stream(thread, print_stream); |
|
1308 objArrayHandle result (thread, objArrayOop(backtrace(throwable))); |
|
1309 if (result.is_null()) { |
|
1310 print_to_stream(stream, no_stack_trace_message()); |
|
1311 return; |
|
1312 } |
|
1313 |
|
1314 while (result.not_null()) { |
|
1315 typeArrayHandle methods(thread, |
|
1316 typeArrayOop(result->obj_at(trace_methods_offset))); |
|
1317 typeArrayHandle bcis (thread, |
|
1318 typeArrayOop(result->obj_at(trace_bcis_offset))); |
|
1319 |
|
1320 if (methods.is_null() || bcis.is_null()) { |
|
1321 print_to_stream(stream, no_stack_trace_message()); |
|
1322 return; |
|
1323 } |
|
1324 |
|
1325 int length = methods()->length(); |
|
1326 for (int index = 0; index < length; index++) { |
|
1327 Method* method = ((Method*)methods()->metadata_at(index)); |
|
1328 if (method == NULL) return; |
|
1329 int bci = bcis->ushort_at(index); |
|
1330 print_stack_element(stream, method, bci); |
|
1331 } |
|
1332 result = objArrayHandle(thread, objArrayOop(result->obj_at(trace_next_offset))); |
|
1333 } |
|
1334 } |
1198 } |
1335 |
1199 |
1336 // This class provides a simple wrapper over the internal structure of |
1200 // This class provides a simple wrapper over the internal structure of |
1337 // exception backtrace to insulate users of the backtrace from needing |
1201 // exception backtrace to insulate users of the backtrace from needing |
1338 // to know what it looks like. |
1202 // to know what it looks like. |
1348 |
1212 |
1349 public: |
1213 public: |
1350 |
1214 |
1351 enum { |
1215 enum { |
1352 trace_methods_offset = java_lang_Throwable::trace_methods_offset, |
1216 trace_methods_offset = java_lang_Throwable::trace_methods_offset, |
1353 trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, |
1217 trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, |
1354 trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, |
1218 trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, |
1355 trace_next_offset = java_lang_Throwable::trace_next_offset, |
1219 trace_next_offset = java_lang_Throwable::trace_next_offset, |
1356 trace_size = java_lang_Throwable::trace_size, |
1220 trace_size = java_lang_Throwable::trace_size, |
1357 trace_chunk_size = java_lang_Throwable::trace_chunk_size |
1221 trace_chunk_size = java_lang_Throwable::trace_chunk_size |
1358 }; |
1222 }; |
1359 |
1223 |
|
1224 // get info out of chunks |
|
1225 static typeArrayOop get_methods(objArrayHandle chunk) { |
|
1226 typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); |
|
1227 assert(methods != NULL, "method array should be initialized in backtrace"); |
|
1228 return methods; |
|
1229 } |
|
1230 static typeArrayOop get_bcis(objArrayHandle chunk) { |
|
1231 typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); |
|
1232 assert(bcis != NULL, "bci array should be initialized in backtrace"); |
|
1233 return bcis; |
|
1234 } |
|
1235 static objArrayOop get_mirrors(objArrayHandle chunk) { |
|
1236 objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); |
|
1237 assert(mirrors != NULL, "mirror array should be initialized in backtrace"); |
|
1238 return mirrors; |
|
1239 } |
|
1240 |
1360 // constructor for new backtrace |
1241 // constructor for new backtrace |
1361 BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL) { |
1242 BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL) { |
1362 expand(CHECK); |
1243 expand(CHECK); |
1363 _backtrace = _head; |
1244 _backtrace = _head; |
1364 _index = 0; |
1245 _index = 0; |
1365 } |
1246 } |
1366 |
1247 |
|
1248 BacktraceBuilder(objArrayHandle backtrace) { |
|
1249 _methods = get_methods(backtrace); |
|
1250 _bcis = get_bcis(backtrace); |
|
1251 _mirrors = get_mirrors(backtrace); |
|
1252 assert(_methods->length() == _bcis->length() && |
|
1253 _methods->length() == _mirrors->length(), |
|
1254 "method and source information arrays should match"); |
|
1255 |
|
1256 // head is the preallocated backtrace |
|
1257 _backtrace = _head = backtrace(); |
|
1258 _index = 0; |
|
1259 } |
|
1260 |
1367 void expand(TRAPS) { |
1261 void expand(TRAPS) { |
1368 objArrayHandle old_head(THREAD, _head); |
1262 objArrayHandle old_head(THREAD, _head); |
1369 Pause_No_Safepoint_Verifier pnsv(&_nsv); |
1263 Pause_No_Safepoint_Verifier pnsv(&_nsv); |
1370 |
1264 |
1371 objArrayOop head = oopFactory::new_objectArray(trace_size, CHECK); |
1265 objArrayOop head = oopFactory::new_objectArray(trace_size, CHECK); |
1372 objArrayHandle new_head(THREAD, head); |
1266 objArrayHandle new_head(THREAD, head); |
1373 |
1267 |
1374 typeArrayOop methods = oopFactory::new_metaDataArray(trace_chunk_size, CHECK); |
1268 typeArrayOop methods = oopFactory::new_shortArray(trace_chunk_size, CHECK); |
1375 typeArrayHandle new_methods(THREAD, methods); |
1269 typeArrayHandle new_methods(THREAD, methods); |
1376 |
1270 |
1377 typeArrayOop bcis = oopFactory::new_shortArray(trace_chunk_size, CHECK); |
1271 typeArrayOop bcis = oopFactory::new_intArray(trace_chunk_size, CHECK); |
1378 typeArrayHandle new_bcis(THREAD, bcis); |
1272 typeArrayHandle new_bcis(THREAD, bcis); |
1379 |
1273 |
1380 objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); |
1274 objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); |
1381 objArrayHandle new_mirrors(THREAD, mirrors); |
1275 objArrayHandle new_mirrors(THREAD, mirrors); |
1382 |
1276 |
1401 inline void push(Method* method, int bci, TRAPS) { |
1295 inline void push(Method* method, int bci, TRAPS) { |
1402 // Smear the -1 bci to 0 since the array only holds unsigned |
1296 // Smear the -1 bci to 0 since the array only holds unsigned |
1403 // shorts. The later line number lookup would just smear the -1 |
1297 // shorts. The later line number lookup would just smear the -1 |
1404 // to a 0 even if it could be recorded. |
1298 // to a 0 even if it could be recorded. |
1405 if (bci == SynchronizationEntryBCI) bci = 0; |
1299 if (bci == SynchronizationEntryBCI) bci = 0; |
1406 assert(bci == (jushort)bci, "doesn't fit"); |
|
1407 |
1300 |
1408 if (_index >= trace_chunk_size) { |
1301 if (_index >= trace_chunk_size) { |
1409 methodHandle mhandle(THREAD, method); |
1302 methodHandle mhandle(THREAD, method); |
1410 expand(CHECK); |
1303 expand(CHECK); |
1411 method = mhandle(); |
1304 method = mhandle(); |
1412 } |
1305 } |
1413 |
1306 |
1414 _methods->metadata_at_put(_index, method); |
1307 _methods->short_at_put(_index, method->method_idnum()); |
1415 _bcis->ushort_at_put(_index, bci); |
1308 _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version())); |
1416 // we need to save the mirrors in the backtrace to keep the methods from |
1309 |
1417 // being unloaded if their class loader is unloaded while we still have |
1310 // We need to save the mirrors in the backtrace to keep the class |
1418 // this stack trace. |
1311 // from being unloaded while we still have this stack trace. |
|
1312 assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror"); |
1419 _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); |
1313 _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); |
1420 _index++; |
1314 _index++; |
1421 } |
1315 } |
1422 |
1316 |
1423 Method* current_method() { |
|
1424 assert(_index >= 0 && _index < trace_chunk_size, "out of range"); |
|
1425 return ((Method*)_methods->metadata_at(_index)); |
|
1426 } |
|
1427 |
|
1428 jushort current_bci() { |
|
1429 assert(_index >= 0 && _index < trace_chunk_size, "out of range"); |
|
1430 return _bcis->ushort_at(_index); |
|
1431 } |
|
1432 }; |
1317 }; |
1433 |
1318 |
|
1319 // Print stack trace element to resource allocated buffer |
|
1320 char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, |
|
1321 int method_id, int version, int bci) { |
|
1322 |
|
1323 // Get strings and string lengths |
|
1324 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
|
1325 const char* klass_name = holder->external_name(); |
|
1326 int buf_len = (int)strlen(klass_name); |
|
1327 |
|
1328 // pushing to the stack trace added one. |
|
1329 Method* method = holder->method_with_idnum(method_id); |
|
1330 char* method_name = method->name()->as_C_string(); |
|
1331 buf_len += (int)strlen(method_name); |
|
1332 |
|
1333 char* source_file_name = NULL; |
|
1334 if (version_matches(method, version)) { |
|
1335 Symbol* source = holder->source_file_name(); |
|
1336 if (source != NULL) { |
|
1337 source_file_name = source->as_C_string(); |
|
1338 buf_len += (int)strlen(source_file_name); |
|
1339 } |
|
1340 } |
|
1341 |
|
1342 // Allocate temporary buffer with extra space for formatting and line number |
|
1343 char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); |
|
1344 |
|
1345 // Print stack trace line in buffer |
|
1346 sprintf(buf, "\tat %s.%s", klass_name, method_name); |
|
1347 |
|
1348 if (!version_matches(method, version)) { |
|
1349 strcat(buf, "(Redefined)"); |
|
1350 } else { |
|
1351 int line_number = get_line_number(method, bci); |
|
1352 if (line_number == -2) { |
|
1353 strcat(buf, "(Native Method)"); |
|
1354 } else { |
|
1355 if (source_file_name != NULL && (line_number != -1)) { |
|
1356 // Sourcename and linenumber |
|
1357 sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number); |
|
1358 } else if (source_file_name != NULL) { |
|
1359 // Just sourcename |
|
1360 sprintf(buf + (int)strlen(buf), "(%s)", source_file_name); |
|
1361 } else { |
|
1362 // Neither sourcename nor linenumber |
|
1363 sprintf(buf + (int)strlen(buf), "(Unknown Source)"); |
|
1364 } |
|
1365 nmethod* nm = method->code(); |
|
1366 if (WizardMode && nm != NULL) { |
|
1367 sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); |
|
1368 } |
|
1369 } |
|
1370 } |
|
1371 |
|
1372 return buf; |
|
1373 } |
|
1374 |
|
1375 void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, |
|
1376 int method_id, int version, int bci) { |
|
1377 ResourceMark rm; |
|
1378 char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci); |
|
1379 st->print_cr("%s", buf); |
|
1380 } |
|
1381 |
|
1382 void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) { |
|
1383 Handle mirror = method->method_holder()->java_mirror(); |
|
1384 int method_id = method->method_idnum(); |
|
1385 int version = method->constants()->version(); |
|
1386 print_stack_element(st, mirror, method_id, version, bci); |
|
1387 } |
|
1388 |
|
1389 const char* java_lang_Throwable::no_stack_trace_message() { |
|
1390 return "\t<<no stack trace available>>"; |
|
1391 } |
|
1392 |
|
1393 |
|
1394 // Currently used only for exceptions occurring during startup |
|
1395 void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) { |
|
1396 Thread *THREAD = Thread::current(); |
|
1397 Handle h_throwable(THREAD, throwable); |
|
1398 while (h_throwable.not_null()) { |
|
1399 objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable()))); |
|
1400 if (result.is_null()) { |
|
1401 st->print_cr(no_stack_trace_message()); |
|
1402 return; |
|
1403 } |
|
1404 |
|
1405 while (result.not_null()) { |
|
1406 |
|
1407 // Get method id, bci, version and mirror from chunk |
|
1408 typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); |
|
1409 typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); |
|
1410 objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); |
|
1411 |
|
1412 int length = methods()->length(); |
|
1413 for (int index = 0; index < length; index++) { |
|
1414 Handle mirror(THREAD, mirrors->obj_at(index)); |
|
1415 // NULL mirror means end of stack trace |
|
1416 if (mirror.is_null()) goto handle_cause; |
|
1417 int method = methods->short_at(index); |
|
1418 int version = version_at(bcis->int_at(index)); |
|
1419 int bci = bci_at(bcis->int_at(index)); |
|
1420 print_stack_element(st, mirror, method, version, bci); |
|
1421 } |
|
1422 result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); |
|
1423 } |
|
1424 handle_cause: |
|
1425 { |
|
1426 EXCEPTION_MARK; |
|
1427 JavaValue cause(T_OBJECT); |
|
1428 JavaCalls::call_virtual(&cause, |
|
1429 h_throwable, |
|
1430 KlassHandle(THREAD, h_throwable->klass()), |
|
1431 vmSymbols::getCause_name(), |
|
1432 vmSymbols::void_throwable_signature(), |
|
1433 THREAD); |
|
1434 // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. |
|
1435 if (HAS_PENDING_EXCEPTION) { |
|
1436 CLEAR_PENDING_EXCEPTION; |
|
1437 h_throwable = Handle(); |
|
1438 } else { |
|
1439 h_throwable = Handle(THREAD, (oop) cause.get_jobject()); |
|
1440 if (h_throwable.not_null()) { |
|
1441 st->print("Caused by: "); |
|
1442 print(h_throwable, st); |
|
1443 st->cr(); |
|
1444 } |
|
1445 } |
|
1446 } |
|
1447 } |
|
1448 } |
1434 |
1449 |
1435 void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS) { |
1450 void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS) { |
1436 if (!StackTraceInThrowable) return; |
1451 if (!StackTraceInThrowable) return; |
1437 ResourceMark rm(THREAD); |
1452 ResourceMark rm(THREAD); |
1438 |
1453 |
1589 void java_lang_Throwable::allocate_backtrace(Handle throwable, TRAPS) { |
1604 void java_lang_Throwable::allocate_backtrace(Handle throwable, TRAPS) { |
1590 // Allocate stack trace - backtrace is created but not filled in |
1605 // Allocate stack trace - backtrace is created but not filled in |
1591 |
1606 |
1592 // No-op if stack trace is disabled |
1607 // No-op if stack trace is disabled |
1593 if (!StackTraceInThrowable) return; |
1608 if (!StackTraceInThrowable) return; |
1594 |
1609 BacktraceBuilder bt(CHECK); // creates a backtrace |
1595 objArrayOop h_oop = oopFactory::new_objectArray(trace_size, CHECK); |
1610 set_backtrace(throwable(), bt.backtrace()); |
1596 objArrayHandle backtrace (THREAD, h_oop); |
|
1597 typeArrayOop m_oop = oopFactory::new_metaDataArray(trace_chunk_size, CHECK); |
|
1598 typeArrayHandle methods (THREAD, m_oop); |
|
1599 typeArrayOop b = oopFactory::new_shortArray(trace_chunk_size, CHECK); |
|
1600 typeArrayHandle bcis(THREAD, b); |
|
1601 objArrayOop mirror_oop = oopFactory::new_objectArray(trace_chunk_size, CHECK); |
|
1602 objArrayHandle mirrors (THREAD, mirror_oop); |
|
1603 |
|
1604 // backtrace has space for one chunk (next is NULL) |
|
1605 backtrace->obj_at_put(trace_methods_offset, methods()); |
|
1606 backtrace->obj_at_put(trace_bcis_offset, bcis()); |
|
1607 backtrace->obj_at_put(trace_mirrors_offset, mirrors()); |
|
1608 set_backtrace(throwable(), backtrace()); |
|
1609 } |
1611 } |
1610 |
1612 |
1611 |
1613 |
1612 void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle throwable) { |
1614 void java_lang_Throwable::fill_in_stack_trace_of_preallocated_backtrace(Handle throwable) { |
1613 // Fill in stack trace into preallocated backtrace (no GC) |
1615 // Fill in stack trace into preallocated backtrace (no GC) |
1615 // No-op if stack trace is disabled |
1617 // No-op if stack trace is disabled |
1616 if (!StackTraceInThrowable) return; |
1618 if (!StackTraceInThrowable) return; |
1617 |
1619 |
1618 assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check"); |
1620 assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check"); |
1619 |
1621 |
1620 objArrayOop backtrace = (objArrayOop)java_lang_Throwable::backtrace(throwable()); |
1622 JavaThread* THREAD = JavaThread::current(); |
1621 assert(backtrace != NULL, "backtrace not preallocated"); |
1623 |
1622 |
1624 objArrayHandle backtrace (THREAD, (objArrayOop)java_lang_Throwable::backtrace(throwable())); |
1623 oop m = backtrace->obj_at(trace_methods_offset); |
1625 assert(backtrace.not_null(), "backtrace should have been preallocated"); |
1624 typeArrayOop methods = typeArrayOop(m); |
1626 |
1625 assert(methods != NULL && methods->length() > 0, "method array not preallocated"); |
1627 ResourceMark rm(THREAD); |
1626 |
1628 vframeStream st(THREAD); |
1627 oop b = backtrace->obj_at(trace_bcis_offset); |
1629 |
1628 typeArrayOop bcis = typeArrayOop(b); |
1630 BacktraceBuilder bt(backtrace); |
1629 assert(bcis != NULL, "bci array not preallocated"); |
|
1630 |
|
1631 oop mr = backtrace->obj_at(trace_mirrors_offset); |
|
1632 objArrayOop mirrors = objArrayOop(mr); |
|
1633 assert(mirrors != NULL, "bci array not preallocated"); |
|
1634 |
|
1635 assert(methods->length() == bcis->length() && |
|
1636 methods->length() == mirrors->length(), |
|
1637 "method and bci arrays should match"); |
|
1638 |
|
1639 JavaThread* thread = JavaThread::current(); |
|
1640 ResourceMark rm(thread); |
|
1641 vframeStream st(thread); |
|
1642 |
1631 |
1643 // Unlike fill_in_stack_trace we do not skip fillInStackTrace or throwable init |
1632 // Unlike fill_in_stack_trace we do not skip fillInStackTrace or throwable init |
1644 // methods as preallocated errors aren't created by "java" code. |
1633 // methods as preallocated errors aren't created by "java" code. |
1645 |
1634 |
1646 // fill in as much stack trace as possible |
1635 // fill in as much stack trace as possible |
|
1636 typeArrayOop methods = BacktraceBuilder::get_methods(backtrace); |
1647 int max_chunks = MIN2(methods->length(), (int)MaxJavaStackTraceDepth); |
1637 int max_chunks = MIN2(methods->length(), (int)MaxJavaStackTraceDepth); |
1648 int chunk_count = 0; |
1638 int chunk_count = 0; |
1649 |
1639 |
1650 for (;!st.at_end(); st.next()) { |
1640 for (;!st.at_end(); st.next()) { |
1651 // Add entry and smear the -1 bci to 0 since the array only holds |
1641 bt.push(st.method(), st.bci(), CHECK); |
1652 // unsigned shorts. The later line number lookup would just smear |
|
1653 // the -1 to a 0 even if it could be recorded. |
|
1654 int bci = st.bci(); |
|
1655 if (bci == SynchronizationEntryBCI) bci = 0; |
|
1656 assert(bci == (jushort)bci, "doesn't fit"); |
|
1657 bcis->ushort_at_put(chunk_count, bci); |
|
1658 methods->metadata_at_put(chunk_count, st.method()); |
|
1659 mirrors->obj_at_put(chunk_count, |
|
1660 st.method()->method_holder()->java_mirror()); |
|
1661 |
|
1662 chunk_count++; |
1642 chunk_count++; |
1663 |
1643 |
1664 // Bail-out for deep stacks |
1644 // Bail-out for deep stacks |
1665 if (chunk_count >= max_chunks) break; |
1645 if (chunk_count >= max_chunks) break; |
1666 } |
1646 } |
1720 skip_chunks--; |
1699 skip_chunks--; |
1721 } |
1700 } |
1722 if (chunk == NULL) { |
1701 if (chunk == NULL) { |
1723 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); |
1702 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); |
1724 } |
1703 } |
1725 // Get method,bci from chunk |
1704 // Get method id, bci, version and mirror from chunk |
1726 typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); |
1705 typeArrayOop methods = BacktraceBuilder::get_methods(chunk); |
1727 typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); |
1706 typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); |
1728 assert(methods != NULL && bcis != NULL, "sanity check"); |
1707 objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); |
1729 methodHandle method(THREAD, ((Method*)methods->metadata_at(chunk_index))); |
1708 |
1730 int bci = bcis->ushort_at(chunk_index); |
1709 assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); |
|
1710 |
|
1711 int method = methods->short_at(chunk_index); |
|
1712 int version = version_at(bcis->int_at(chunk_index)); |
|
1713 int bci = bci_at(bcis->int_at(chunk_index)); |
|
1714 Handle mirror(THREAD, mirrors->obj_at(chunk_index)); |
|
1715 |
1731 // Chunk can be partial full |
1716 // Chunk can be partial full |
1732 if (method.is_null()) { |
1717 if (mirror.is_null()) { |
1733 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); |
1718 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); |
1734 } |
1719 } |
1735 |
1720 |
1736 oop element = java_lang_StackTraceElement::create(method, bci, CHECK_0); |
1721 oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, CHECK_0); |
1737 return element; |
1722 return element; |
1738 } |
1723 } |
1739 |
1724 |
1740 oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { |
1725 oop java_lang_StackTraceElement::create(Handle mirror, int method_id, int version, int bci, TRAPS) { |
1741 // SystemDictionary::stackTraceElement_klass() will be null for pre-1.4 JDKs |
|
1742 assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4"); |
|
1743 |
|
1744 // Allocate java.lang.StackTraceElement instance |
1726 // Allocate java.lang.StackTraceElement instance |
1745 Klass* k = SystemDictionary::StackTraceElement_klass(); |
1727 Klass* k = SystemDictionary::StackTraceElement_klass(); |
1746 assert(k != NULL, "must be loaded in 1.4+"); |
1728 assert(k != NULL, "must be loaded in 1.4+"); |
1747 instanceKlassHandle ik (THREAD, k); |
1729 instanceKlassHandle ik (THREAD, k); |
1748 if (ik->should_be_initialized()) { |
1730 if (ik->should_be_initialized()) { |
1750 } |
1732 } |
1751 |
1733 |
1752 Handle element = ik->allocate_instance_handle(CHECK_0); |
1734 Handle element = ik->allocate_instance_handle(CHECK_0); |
1753 // Fill in class name |
1735 // Fill in class name |
1754 ResourceMark rm(THREAD); |
1736 ResourceMark rm(THREAD); |
1755 const char* str = method->method_holder()->external_name(); |
1737 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); |
|
1738 const char* str = holder->external_name(); |
1756 oop classname = StringTable::intern((char*) str, CHECK_0); |
1739 oop classname = StringTable::intern((char*) str, CHECK_0); |
1757 java_lang_StackTraceElement::set_declaringClass(element(), classname); |
1740 java_lang_StackTraceElement::set_declaringClass(element(), classname); |
|
1741 |
1758 // Fill in method name |
1742 // Fill in method name |
|
1743 Method* method = holder->method_with_idnum(method_id); |
1759 oop methodname = StringTable::intern(method->name(), CHECK_0); |
1744 oop methodname = StringTable::intern(method->name(), CHECK_0); |
1760 java_lang_StackTraceElement::set_methodName(element(), methodname); |
1745 java_lang_StackTraceElement::set_methodName(element(), methodname); |
1761 // Fill in source file name |
1746 |
1762 Symbol* source = method->method_holder()->source_file_name(); |
1747 if (!version_matches(method, version)) { |
1763 if (ShowHiddenFrames && source == NULL) |
1748 // The method was redefined, accurate line number information isn't available |
1764 source = vmSymbols::unknown_class_name(); |
1749 java_lang_StackTraceElement::set_fileName(element(), NULL); |
1765 oop filename = StringTable::intern(source, CHECK_0); |
1750 java_lang_StackTraceElement::set_lineNumber(element(), -1); |
1766 java_lang_StackTraceElement::set_fileName(element(), filename); |
|
1767 // File in source line number |
|
1768 int line_number; |
|
1769 if (method->is_native()) { |
|
1770 // Negative value different from -1 below, enabling Java code in |
|
1771 // class java.lang.StackTraceElement to distinguish "native" from |
|
1772 // "no LineNumberTable". |
|
1773 line_number = -2; |
|
1774 } else { |
1751 } else { |
1775 // Returns -1 if no LineNumberTable, and otherwise actual line number |
1752 // Fill in source file name and line number. |
1776 line_number = method->line_number_from_bci(bci); |
1753 Symbol* source = holder->source_file_name(); |
1777 if (line_number == -1 && ShowHiddenFrames) { |
1754 if (ShowHiddenFrames && source == NULL) |
1778 line_number = bci + 1000000; |
1755 source = vmSymbols::unknown_class_name(); |
1779 } |
1756 oop filename = StringTable::intern(source, CHECK_0); |
1780 } |
1757 java_lang_StackTraceElement::set_fileName(element(), filename); |
1781 java_lang_StackTraceElement::set_lineNumber(element(), line_number); |
1758 |
1782 |
1759 int line_number = get_line_number(method, bci); |
|
1760 java_lang_StackTraceElement::set_lineNumber(element(), line_number); |
|
1761 } |
1783 return element(); |
1762 return element(); |
1784 } |
1763 } |
1785 |
1764 |
|
1765 oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { |
|
1766 Handle mirror (THREAD, method->method_holder()->java_mirror()); |
|
1767 int method_id = method->method_idnum(); |
|
1768 return create(mirror, method_id, method->constants()->version(), bci, THREAD); |
|
1769 } |
1786 |
1770 |
1787 void java_lang_reflect_AccessibleObject::compute_offsets() { |
1771 void java_lang_reflect_AccessibleObject::compute_offsets() { |
1788 Klass* k = SystemDictionary::reflect_AccessibleObject_klass(); |
1772 Klass* k = SystemDictionary::reflect_AccessibleObject_klass(); |
1789 compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature()); |
1773 compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature()); |
1790 } |
1774 } |