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