1342 // a missing receiver might result in a bogus lookup. |
1342 // a missing receiver might result in a bogus lookup. |
1343 assert(resolved_method->method_holder()->is_linked(), "must be linked"); |
1343 assert(resolved_method->method_holder()->is_linked(), "must be linked"); |
1344 |
1344 |
1345 // do lookup based on receiver klass using the vtable index |
1345 // do lookup based on receiver klass using the vtable index |
1346 if (resolved_method->method_holder()->is_interface()) { // default or miranda method |
1346 if (resolved_method->method_holder()->is_interface()) { // default or miranda method |
1347 vtable_index = vtable_index_of_interface_method(resolved_klass, |
1347 vtable_index = vtable_index_of_interface_method(resolved_klass, resolved_method); |
1348 resolved_method); |
|
1349 assert(vtable_index >= 0 , "we should have valid vtable index at this point"); |
1348 assert(vtable_index >= 0 , "we should have valid vtable index at this point"); |
1350 |
1349 |
1351 selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index)); |
1350 selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index)); |
1352 } else { |
1351 } else { |
1353 // at this point we are sure that resolved_method is virtual and not |
1352 // at this point we are sure that resolved_method is virtual and not |
1354 // a default or miranda method; therefore, it must have a valid vtable index. |
1353 // a default or miranda method; therefore, it must have a valid vtable index. |
1355 assert(!resolved_method->has_itable_index(), ""); |
1354 assert(!resolved_method->has_itable_index(), ""); |
1356 vtable_index = resolved_method->vtable_index(); |
1355 vtable_index = resolved_method->vtable_index(); |
1357 // We could get a negative vtable_index for final methods, |
1356 // We could get a negative vtable_index for final methods, |
1358 // because as an optimization they are they are never put in the vtable, |
1357 // because as an optimization they are never put in the vtable, |
1359 // unless they override an existing method. |
1358 // unless they override an existing method. |
1360 // If we do get a negative, it means the resolved method is the the selected |
1359 // If we do get a negative, it means the resolved method is the the selected |
1361 // method, and it can never be changed by an override. |
1360 // method, and it can never be changed by an override. |
1362 if (vtable_index == Method::nonvirtual_vtable_index) { |
1361 if (vtable_index == Method::nonvirtual_vtable_index) { |
1363 assert(resolved_method->can_be_statically_bound(), "cannot override this method"); |
1362 assert(resolved_method->can_be_statically_bound(), "cannot override this method"); |
1367 } |
1366 } |
1368 } |
1367 } |
1369 |
1368 |
1370 // check if method exists |
1369 // check if method exists |
1371 if (selected_method.is_null()) { |
1370 if (selected_method.is_null()) { |
1372 ResourceMark rm(THREAD); |
1371 throw_abstract_method_error(resolved_method, recv_klass, CHECK); |
1373 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
|
1374 Method::name_and_sig_as_C_string(resolved_klass, |
|
1375 resolved_method->name(), |
|
1376 resolved_method->signature())); |
|
1377 } |
1372 } |
1378 |
1373 |
1379 // check if abstract |
1374 // check if abstract |
1380 if (check_null_and_abstract && selected_method->is_abstract()) { |
1375 if (check_null_and_abstract && selected_method->is_abstract()) { |
1381 ResourceMark rm(THREAD); |
1376 // Pass arguments for generating a verbose error message. |
1382 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1377 throw_abstract_method_error(resolved_method, selected_method, recv_klass, CHECK); |
1383 Method::name_and_sig_as_C_string(resolved_klass, |
|
1384 selected_method->name(), |
|
1385 selected_method->signature())); |
|
1386 } |
1378 } |
1387 |
1379 |
1388 if (log_develop_is_enabled(Trace, vtables)) { |
1380 if (log_develop_is_enabled(Trace, vtables)) { |
1389 trace_method_resolution("invokevirtual selected method: receiver-class:", |
1381 trace_method_resolution("invokevirtual selected method: receiver-class:", |
1390 recv_klass, resolved_klass, selected_method, |
1382 recv_klass, resolved_klass, selected_method, |
1436 } |
1428 } |
1437 |
1429 |
1438 // do lookup based on receiver klass |
1430 // do lookup based on receiver klass |
1439 // This search must match the linktime preparation search for itable initialization |
1431 // This search must match the linktime preparation search for itable initialization |
1440 // to correctly enforce loader constraints for interface method inheritance |
1432 // to correctly enforce loader constraints for interface method inheritance |
1441 methodHandle sel_method = lookup_instance_method_in_klasses(recv_klass, |
1433 methodHandle selected_method = lookup_instance_method_in_klasses(recv_klass, |
1442 resolved_method->name(), |
1434 resolved_method->name(), |
1443 resolved_method->signature(), CHECK); |
1435 resolved_method->signature(), CHECK); |
1444 if (sel_method.is_null() && !check_null_and_abstract) { |
1436 if (selected_method.is_null() && !check_null_and_abstract) { |
1445 // In theory this is a harmless placeholder value, but |
1437 // In theory this is a harmless placeholder value, but |
1446 // in practice leaving in null affects the nsk default method tests. |
1438 // in practice leaving in null affects the nsk default method tests. |
1447 // This needs further study. |
1439 // This needs further study. |
1448 sel_method = resolved_method; |
1440 selected_method = resolved_method; |
1449 } |
1441 } |
1450 // check if method exists |
1442 // check if method exists |
1451 if (sel_method.is_null()) { |
1443 if (selected_method.is_null()) { |
1452 ResourceMark rm(THREAD); |
1444 // Pass arguments for generating a verbose error message. |
1453 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1445 throw_abstract_method_error(resolved_method, recv_klass, CHECK); |
1454 Method::name_and_sig_as_C_string(recv_klass, |
|
1455 resolved_method->name(), |
|
1456 resolved_method->signature())); |
|
1457 } |
1446 } |
1458 // check access |
1447 // check access |
1459 // Throw Illegal Access Error if sel_method is not public. |
1448 // Throw Illegal Access Error if selected_method is not public. |
1460 if (!sel_method->is_public()) { |
1449 if (!selected_method->is_public()) { |
1461 ResourceMark rm(THREAD); |
1450 ResourceMark rm(THREAD); |
1462 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), |
1451 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), |
1463 Method::name_and_sig_as_C_string(recv_klass, |
1452 Method::name_and_sig_as_C_string(recv_klass, |
1464 sel_method->name(), |
1453 selected_method->name(), |
1465 sel_method->signature())); |
1454 selected_method->signature())); |
1466 } |
1455 } |
1467 // check if abstract |
1456 // check if abstract |
1468 if (check_null_and_abstract && sel_method->is_abstract()) { |
1457 if (check_null_and_abstract && selected_method->is_abstract()) { |
1469 ResourceMark rm(THREAD); |
1458 throw_abstract_method_error(resolved_method, selected_method, recv_klass, CHECK); |
1470 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
|
1471 Method::name_and_sig_as_C_string(recv_klass, |
|
1472 sel_method->name(), |
|
1473 sel_method->signature())); |
|
1474 } |
1459 } |
1475 |
1460 |
1476 if (log_develop_is_enabled(Trace, itables)) { |
1461 if (log_develop_is_enabled(Trace, itables)) { |
1477 trace_method_resolution("invokeinterface selected method: receiver-class:", |
1462 trace_method_resolution("invokeinterface selected method: receiver-class:", |
1478 recv_klass, resolved_klass, sel_method, true); |
1463 recv_klass, resolved_klass, selected_method, true); |
1479 } |
1464 } |
1480 // setup result |
1465 // setup result |
1481 if (!resolved_method->has_itable_index()) { |
1466 if (!resolved_method->has_itable_index()) { |
1482 int vtable_index = resolved_method->vtable_index(); |
1467 int vtable_index = resolved_method->vtable_index(); |
1483 assert(vtable_index == sel_method->vtable_index(), "sanity check"); |
1468 assert(vtable_index == selected_method->vtable_index(), "sanity check"); |
1484 result.set_virtual(resolved_klass, recv_klass, resolved_method, sel_method, vtable_index, CHECK); |
1469 result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK); |
1485 } else { |
1470 } else { |
1486 int itable_index = resolved_method()->itable_index(); |
1471 int itable_index = resolved_method()->itable_index(); |
1487 result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, itable_index, CHECK); |
1472 result.set_interface(resolved_klass, recv_klass, resolved_method, selected_method, itable_index, CHECK); |
1488 } |
1473 } |
1489 } |
1474 } |
1490 |
1475 |
1491 |
1476 |
1492 methodHandle LinkResolver::linktime_resolve_interface_method_or_null( |
1477 methodHandle LinkResolver::linktime_resolve_interface_method_or_null( |
1772 THREAD); |
1757 THREAD); |
1773 Exceptions::wrap_dynamic_exception(CHECK); |
1758 Exceptions::wrap_dynamic_exception(CHECK); |
1774 result.set_handle(resolved_method, resolved_appendix, resolved_method_type, THREAD); |
1759 result.set_handle(resolved_method, resolved_appendix, resolved_method_type, THREAD); |
1775 Exceptions::wrap_dynamic_exception(CHECK); |
1760 Exceptions::wrap_dynamic_exception(CHECK); |
1776 } |
1761 } |
|
1762 |
|
1763 // Selected method is abstract. |
|
1764 void LinkResolver::throw_abstract_method_error(const methodHandle& resolved_method, |
|
1765 const methodHandle& selected_method, |
|
1766 Klass *recv_klass, TRAPS) { |
|
1767 Klass *resolved_klass = resolved_method->method_holder(); |
|
1768 ResourceMark rm(THREAD); |
|
1769 stringStream ss; |
|
1770 |
|
1771 if (recv_klass != NULL) { |
|
1772 ss.print("Receiver class %s does not define or inherit an " |
|
1773 "implementation of the", |
|
1774 recv_klass->external_name()); |
|
1775 } else { |
|
1776 ss.print("Missing implementation of"); |
|
1777 } |
|
1778 |
|
1779 assert(resolved_method.not_null(), "Sanity"); |
|
1780 ss.print(" resolved method %s%s%s%s of %s %s.", |
|
1781 resolved_method->is_abstract() ? "abstract " : "", |
|
1782 resolved_method->is_private() ? "private " : "", |
|
1783 resolved_method->name()->as_C_string(), |
|
1784 resolved_method->signature()->as_C_string(), |
|
1785 resolved_klass->external_kind(), |
|
1786 resolved_klass->external_name()); |
|
1787 |
|
1788 if (selected_method.not_null() && !(resolved_method == selected_method)) { |
|
1789 ss.print(" Selected method is %s%s%s.", |
|
1790 selected_method->is_abstract() ? "abstract " : "", |
|
1791 selected_method->is_private() ? "private " : "", |
|
1792 selected_method->name_and_sig_as_C_string()); |
|
1793 } |
|
1794 |
|
1795 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string()); |
|
1796 } |