comparison src/share/vm/classfile/javaClasses.cpp @ 22933:1a9c5e6e13b7

8067662: "java.lang.NullPointerException: Method name is null" from StackTraceElement.<init> Summary: use method cpref and klass version to provide meaningful methods name in stacktraces Reviewed-by: coleenp, dcubed
author sspitsyn
date Wed, 08 Apr 2015 14:20:09 -0700
parents fe34c5ab0b35
children c97ba20ad404
comparison
equal deleted inserted replaced
22932:04e84c0579be 22933:1a9c5e6e13b7
1 /* 1 /*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 1997, 2015, 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.
1276 static inline int version_at(unsigned int merged) { 1276 static inline int version_at(unsigned int merged) {
1277 return extract_low_short_from_int(merged); 1277 return extract_low_short_from_int(merged);
1278 } 1278 }
1279 1279
1280 static inline bool version_matches(Method* method, int version) { 1280 static inline bool version_matches(Method* method, int version) {
1281 return (method->constants()->version() == version && version < MAX_VERSION); 1281 assert(version < MAX_VERSION, "version is too big");
1282 return method != NULL && (method->constants()->version() == version);
1282 } 1283 }
1283 1284
1284 static inline int get_line_number(Method* method, int bci) { 1285 static inline int get_line_number(Method* method, int bci) {
1285 int line_number = 0; 1286 int line_number = 0;
1286 if (method->is_native()) { 1287 if (method->is_native()) {
1306 Handle _backtrace; 1307 Handle _backtrace;
1307 objArrayOop _head; 1308 objArrayOop _head;
1308 typeArrayOop _methods; 1309 typeArrayOop _methods;
1309 typeArrayOop _bcis; 1310 typeArrayOop _bcis;
1310 objArrayOop _mirrors; 1311 objArrayOop _mirrors;
1312 typeArrayOop _cprefs; // needed to insulate method name against redefinition
1311 int _index; 1313 int _index;
1312 No_Safepoint_Verifier _nsv; 1314 No_Safepoint_Verifier _nsv;
1313 1315
1314 public: 1316 public:
1315 1317
1316 enum { 1318 enum {
1317 trace_methods_offset = java_lang_Throwable::trace_methods_offset, 1319 trace_methods_offset = java_lang_Throwable::trace_methods_offset,
1318 trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, 1320 trace_bcis_offset = java_lang_Throwable::trace_bcis_offset,
1319 trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, 1321 trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset,
1322 trace_cprefs_offset = java_lang_Throwable::trace_cprefs_offset,
1320 trace_next_offset = java_lang_Throwable::trace_next_offset, 1323 trace_next_offset = java_lang_Throwable::trace_next_offset,
1321 trace_size = java_lang_Throwable::trace_size, 1324 trace_size = java_lang_Throwable::trace_size,
1322 trace_chunk_size = java_lang_Throwable::trace_chunk_size 1325 trace_chunk_size = java_lang_Throwable::trace_chunk_size
1323 }; 1326 };
1324 1327
1336 static objArrayOop get_mirrors(objArrayHandle chunk) { 1339 static objArrayOop get_mirrors(objArrayHandle chunk) {
1337 objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); 1340 objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset));
1338 assert(mirrors != NULL, "mirror array should be initialized in backtrace"); 1341 assert(mirrors != NULL, "mirror array should be initialized in backtrace");
1339 return mirrors; 1342 return mirrors;
1340 } 1343 }
1344 static typeArrayOop get_cprefs(objArrayHandle chunk) {
1345 typeArrayOop cprefs = typeArrayOop(chunk->obj_at(trace_cprefs_offset));
1346 assert(cprefs != NULL, "cprefs array should be initialized in backtrace");
1347 return cprefs;
1348 }
1341 1349
1342 // constructor for new backtrace 1350 // constructor for new backtrace
1343 BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL) { 1351 BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _cprefs(NULL) {
1344 expand(CHECK); 1352 expand(CHECK);
1345 _backtrace = _head; 1353 _backtrace = _head;
1346 _index = 0; 1354 _index = 0;
1347 } 1355 }
1348 1356
1349 BacktraceBuilder(objArrayHandle backtrace) { 1357 BacktraceBuilder(objArrayHandle backtrace) {
1350 _methods = get_methods(backtrace); 1358 _methods = get_methods(backtrace);
1351 _bcis = get_bcis(backtrace); 1359 _bcis = get_bcis(backtrace);
1352 _mirrors = get_mirrors(backtrace); 1360 _mirrors = get_mirrors(backtrace);
1361 _cprefs = get_cprefs(backtrace);
1353 assert(_methods->length() == _bcis->length() && 1362 assert(_methods->length() == _bcis->length() &&
1354 _methods->length() == _mirrors->length(), 1363 _methods->length() == _mirrors->length(),
1355 "method and source information arrays should match"); 1364 "method and source information arrays should match");
1356 1365
1357 // head is the preallocated backtrace 1366 // head is the preallocated backtrace
1373 typeArrayHandle new_bcis(THREAD, bcis); 1382 typeArrayHandle new_bcis(THREAD, bcis);
1374 1383
1375 objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); 1384 objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK);
1376 objArrayHandle new_mirrors(THREAD, mirrors); 1385 objArrayHandle new_mirrors(THREAD, mirrors);
1377 1386
1387 typeArrayOop cprefs = oopFactory::new_shortArray(trace_chunk_size, CHECK);
1388 typeArrayHandle new_cprefs(THREAD, cprefs);
1389
1378 if (!old_head.is_null()) { 1390 if (!old_head.is_null()) {
1379 old_head->obj_at_put(trace_next_offset, new_head()); 1391 old_head->obj_at_put(trace_next_offset, new_head());
1380 } 1392 }
1381 new_head->obj_at_put(trace_methods_offset, new_methods()); 1393 new_head->obj_at_put(trace_methods_offset, new_methods());
1382 new_head->obj_at_put(trace_bcis_offset, new_bcis()); 1394 new_head->obj_at_put(trace_bcis_offset, new_bcis());
1383 new_head->obj_at_put(trace_mirrors_offset, new_mirrors()); 1395 new_head->obj_at_put(trace_mirrors_offset, new_mirrors());
1396 new_head->obj_at_put(trace_cprefs_offset, new_cprefs());
1384 1397
1385 _head = new_head(); 1398 _head = new_head();
1386 _methods = new_methods(); 1399 _methods = new_methods();
1387 _bcis = new_bcis(); 1400 _bcis = new_bcis();
1388 _mirrors = new_mirrors(); 1401 _mirrors = new_mirrors();
1402 _cprefs = new_cprefs();
1389 _index = 0; 1403 _index = 0;
1390 } 1404 }
1391 1405
1392 oop backtrace() { 1406 oop backtrace() {
1393 return _backtrace(); 1407 return _backtrace();
1403 methodHandle mhandle(THREAD, method); 1417 methodHandle mhandle(THREAD, method);
1404 expand(CHECK); 1418 expand(CHECK);
1405 method = mhandle(); 1419 method = mhandle();
1406 } 1420 }
1407 1421
1408 _methods->short_at_put(_index, method->method_idnum()); 1422 _methods->short_at_put(_index, method->orig_method_idnum());
1409 _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version())); 1423 _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version()));
1424 _cprefs->short_at_put(_index, method->name_index());
1410 1425
1411 // We need to save the mirrors in the backtrace to keep the class 1426 // We need to save the mirrors in the backtrace to keep the class
1412 // from being unloaded while we still have this stack trace. 1427 // from being unloaded while we still have this stack trace.
1413 assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror"); 1428 assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror");
1414 _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); 1429 _mirrors->obj_at_put(_index, method->method_holder()->java_mirror());
1417 1432
1418 }; 1433 };
1419 1434
1420 // Print stack trace element to resource allocated buffer 1435 // Print stack trace element to resource allocated buffer
1421 char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, 1436 char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
1422 int method_id, int version, int bci) { 1437 int method_id, int version, int bci, int cpref) {
1423 1438
1424 // Get strings and string lengths 1439 // Get strings and string lengths
1425 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); 1440 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror()));
1426 const char* klass_name = holder->external_name(); 1441 const char* klass_name = holder->external_name();
1427 int buf_len = (int)strlen(klass_name); 1442 int buf_len = (int)strlen(klass_name);
1428 1443
1429 // The method id may point to an obsolete method, can't get more stack information 1444 Method* method = holder->method_with_orig_idnum(method_id, version);
1430 Method* method = holder->method_with_idnum(method_id); 1445
1431 if (method == NULL) { 1446 // The method can be NULL if the requested class version is gone
1432 char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); 1447 Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref);
1433 // This is what the java code prints in this case - added Redefined 1448 char* method_name = sym->as_C_string();
1434 sprintf(buf, "\tat %s.null (Redefined)", klass_name);
1435 return buf;
1436 }
1437
1438 char* method_name = method->name()->as_C_string();
1439 buf_len += (int)strlen(method_name); 1449 buf_len += (int)strlen(method_name);
1440 1450
1451 // Use a specific ik version as a holder since the mirror might
1452 // refer to a version that is now obsolete and no longer accessible
1453 // via the previous versions list.
1454 holder = holder->get_klass_version(version);
1441 char* source_file_name = NULL; 1455 char* source_file_name = NULL;
1442 if (version_matches(method, version)) { 1456 if (holder != NULL) {
1443 Symbol* source = holder->source_file_name(); 1457 Symbol* source = holder->source_file_name();
1444 if (source != NULL) { 1458 if (source != NULL) {
1445 source_file_name = source->as_C_string(); 1459 source_file_name = source->as_C_string();
1446 buf_len += (int)strlen(source_file_name); 1460 buf_len += (int)strlen(source_file_name);
1447 } 1461 }
1479 1493
1480 return buf; 1494 return buf;
1481 } 1495 }
1482 1496
1483 void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, 1497 void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror,
1484 int method_id, int version, int bci) { 1498 int method_id, int version, int bci, int cpref) {
1485 ResourceMark rm; 1499 ResourceMark rm;
1486 char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci); 1500 char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci, cpref);
1487 st->print_cr("%s", buf); 1501 st->print_cr("%s", buf);
1488 } 1502 }
1489 1503
1490 void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) { 1504 void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) {
1491 Handle mirror = method->method_holder()->java_mirror(); 1505 Handle mirror = method->method_holder()->java_mirror();
1492 int method_id = method->method_idnum(); 1506 int method_id = method->orig_method_idnum();
1493 int version = method->constants()->version(); 1507 int version = method->constants()->version();
1494 print_stack_element(st, mirror, method_id, version, bci); 1508 int cpref = method->name_index();
1509 print_stack_element(st, mirror, method_id, version, bci, cpref);
1495 } 1510 }
1496 1511
1497 const char* java_lang_Throwable::no_stack_trace_message() { 1512 const char* java_lang_Throwable::no_stack_trace_message() {
1498 return "\t<<no stack trace available>>"; 1513 return "\t<<no stack trace available>>";
1499 } 1514 }
1514 1529
1515 // Get method id, bci, version and mirror from chunk 1530 // Get method id, bci, version and mirror from chunk
1516 typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); 1531 typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result));
1517 typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); 1532 typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result));
1518 objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); 1533 objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result));
1534 typeArrayHandle cprefs (THREAD, BacktraceBuilder::get_cprefs(result));
1519 1535
1520 int length = methods()->length(); 1536 int length = methods()->length();
1521 for (int index = 0; index < length; index++) { 1537 for (int index = 0; index < length; index++) {
1522 Handle mirror(THREAD, mirrors->obj_at(index)); 1538 Handle mirror(THREAD, mirrors->obj_at(index));
1523 // NULL mirror means end of stack trace 1539 // NULL mirror means end of stack trace
1524 if (mirror.is_null()) goto handle_cause; 1540 if (mirror.is_null()) goto handle_cause;
1525 int method = methods->short_at(index); 1541 int method = methods->short_at(index);
1526 int version = version_at(bcis->int_at(index)); 1542 int version = version_at(bcis->int_at(index));
1527 int bci = bci_at(bcis->int_at(index)); 1543 int bci = bci_at(bcis->int_at(index));
1528 print_stack_element(st, mirror, method, version, bci); 1544 int cpref = cprefs->short_at(index);
1545 print_stack_element(st, mirror, method, version, bci, cpref);
1529 } 1546 }
1530 result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); 1547 result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset)));
1531 } 1548 }
1532 handle_cause: 1549 handle_cause:
1533 { 1550 {
1807 skip_chunks--; 1824 skip_chunks--;
1808 } 1825 }
1809 if (chunk == NULL) { 1826 if (chunk == NULL) {
1810 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); 1827 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL);
1811 } 1828 }
1812 // Get method id, bci, version and mirror from chunk 1829 // Get method id, bci, version, mirror and cpref from chunk
1813 typeArrayOop methods = BacktraceBuilder::get_methods(chunk); 1830 typeArrayOop methods = BacktraceBuilder::get_methods(chunk);
1814 typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); 1831 typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk);
1815 objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); 1832 objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk);
1833 typeArrayOop cprefs = BacktraceBuilder::get_cprefs(chunk);
1816 1834
1817 assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); 1835 assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check");
1818 1836
1819 int method = methods->short_at(chunk_index); 1837 int method = methods->short_at(chunk_index);
1820 int version = version_at(bcis->int_at(chunk_index)); 1838 int version = version_at(bcis->int_at(chunk_index));
1821 int bci = bci_at(bcis->int_at(chunk_index)); 1839 int bci = bci_at(bcis->int_at(chunk_index));
1840 int cpref = cprefs->short_at(chunk_index);
1822 Handle mirror(THREAD, mirrors->obj_at(chunk_index)); 1841 Handle mirror(THREAD, mirrors->obj_at(chunk_index));
1823 1842
1824 // Chunk can be partial full 1843 // Chunk can be partial full
1825 if (mirror.is_null()) { 1844 if (mirror.is_null()) {
1826 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); 1845 THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL);
1827 } 1846 }
1828 1847 oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, cpref, CHECK_0);
1829 oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, CHECK_0);
1830 return element; 1848 return element;
1831 } 1849 }
1832 1850
1833 oop java_lang_StackTraceElement::create(Handle mirror, int method_id, 1851 oop java_lang_StackTraceElement::create(Handle mirror, int method_id,
1834 int version, int bci, TRAPS) { 1852 int version, int bci, int cpref, TRAPS) {
1835 // Allocate java.lang.StackTraceElement instance 1853 // Allocate java.lang.StackTraceElement instance
1836 Klass* k = SystemDictionary::StackTraceElement_klass(); 1854 Klass* k = SystemDictionary::StackTraceElement_klass();
1837 assert(k != NULL, "must be loaded in 1.4+"); 1855 assert(k != NULL, "must be loaded in 1.4+");
1838 instanceKlassHandle ik (THREAD, k); 1856 instanceKlassHandle ik (THREAD, k);
1839 if (ik->should_be_initialized()) { 1857 if (ik->should_be_initialized()) {
1846 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); 1864 InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror()));
1847 const char* str = holder->external_name(); 1865 const char* str = holder->external_name();
1848 oop classname = StringTable::intern((char*) str, CHECK_0); 1866 oop classname = StringTable::intern((char*) str, CHECK_0);
1849 java_lang_StackTraceElement::set_declaringClass(element(), classname); 1867 java_lang_StackTraceElement::set_declaringClass(element(), classname);
1850 1868
1851 Method* method = holder->method_with_idnum(method_id); 1869 Method* method = holder->method_with_orig_idnum(method_id, version);
1852 // Method on stack may be obsolete because it was redefined so cannot be 1870
1853 // found by idnum. 1871 // The method can be NULL if the requested class version is gone
1854 if (method == NULL) { 1872 Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref);
1855 // leave name and fileName null
1856 java_lang_StackTraceElement::set_lineNumber(element(), -1);
1857 return element();
1858 }
1859 1873
1860 // Fill in method name 1874 // Fill in method name
1861 oop methodname = StringTable::intern(method->name(), CHECK_0); 1875 oop methodname = StringTable::intern(sym, CHECK_0);
1862 java_lang_StackTraceElement::set_methodName(element(), methodname); 1876 java_lang_StackTraceElement::set_methodName(element(), methodname);
1863 1877
1864 if (!version_matches(method, version)) { 1878 if (!version_matches(method, version)) {
1865 // The method was redefined, accurate line number information isn't available 1879 // The method was redefined, accurate line number information isn't available
1866 java_lang_StackTraceElement::set_fileName(element(), NULL); 1880 java_lang_StackTraceElement::set_fileName(element(), NULL);
1867 java_lang_StackTraceElement::set_lineNumber(element(), -1); 1881 java_lang_StackTraceElement::set_lineNumber(element(), -1);
1868 } else { 1882 } else {
1869 // Fill in source file name and line number. 1883 // Fill in source file name and line number.
1884 // Use a specific ik version as a holder since the mirror might
1885 // refer to a version that is now obsolete and no longer accessible
1886 // via the previous versions list.
1887 holder = holder->get_klass_version(version);
1888 assert(holder != NULL, "sanity check");
1870 Symbol* source = holder->source_file_name(); 1889 Symbol* source = holder->source_file_name();
1871 if (ShowHiddenFrames && source == NULL) 1890 if (ShowHiddenFrames && source == NULL)
1872 source = vmSymbols::unknown_class_name(); 1891 source = vmSymbols::unknown_class_name();
1873 oop filename = StringTable::intern(source, CHECK_0); 1892 oop filename = StringTable::intern(source, CHECK_0);
1874 java_lang_StackTraceElement::set_fileName(element(), filename); 1893 java_lang_StackTraceElement::set_fileName(element(), filename);
1879 return element(); 1898 return element();
1880 } 1899 }
1881 1900
1882 oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { 1901 oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
1883 Handle mirror (THREAD, method->method_holder()->java_mirror()); 1902 Handle mirror (THREAD, method->method_holder()->java_mirror());
1884 int method_id = method->method_idnum(); 1903 int method_id = method->orig_method_idnum();
1885 return create(mirror, method_id, method->constants()->version(), bci, THREAD); 1904 int cpref = method->name_index();
1905 return create(mirror, method_id, method->constants()->version(), bci, cpref, THREAD);
1886 } 1906 }
1887 1907
1888 void java_lang_reflect_AccessibleObject::compute_offsets() { 1908 void java_lang_reflect_AccessibleObject::compute_offsets() {
1889 Klass* k = SystemDictionary::reflect_AccessibleObject_klass(); 1909 Klass* k = SystemDictionary::reflect_AccessibleObject_klass();
1890 compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature()); 1910 compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature());