< prev index next >

src/hotspot/share/interpreter/linkResolver.cpp

Print this page
rev 49028 : 8197405: Improve messages of AbstractMethodErrors and IncompatibleClassChangeErrors.
Reviewed-by: coleenp, dholmes, mdoerr


1326                                                   Klass* recv_klass,
1327                                                   bool check_null_and_abstract,
1328                                                   TRAPS) {
1329 
1330   // setup default return values
1331   int vtable_index = Method::invalid_vtable_index;
1332   methodHandle selected_method;
1333 
1334   // runtime method resolution
1335   if (check_null_and_abstract && recv.is_null()) { // check if receiver exists
1336     THROW(vmSymbols::java_lang_NullPointerException());
1337   }
1338 
1339   // Virtual methods cannot be resolved before its klass has been linked, for otherwise the Method*'s
1340   // has not been rewritten, and the vtable initialized. Make sure to do this after the nullcheck, since
1341   // a missing receiver might result in a bogus lookup.
1342   assert(resolved_method->method_holder()->is_linked(), "must be linked");
1343 
1344   // do lookup based on receiver klass using the vtable index
1345   if (resolved_method->method_holder()->is_interface()) { // default or miranda method
1346     vtable_index = vtable_index_of_interface_method(resolved_klass,
1347                            resolved_method);
1348     assert(vtable_index >= 0 , "we should have valid vtable index at this point");
1349 
1350     selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index));
1351   } else {
1352     // at this point we are sure that resolved_method is virtual and not
1353     // a default or miranda method; therefore, it must have a valid vtable index.
1354     assert(!resolved_method->has_itable_index(), "");
1355     vtable_index = resolved_method->vtable_index();
1356     // We could get a negative vtable_index for final methods,
1357     // because as an optimization they are they are never put in the vtable,
1358     // unless they override an existing method.
1359     // If we do get a negative, it means the resolved method is the the selected
1360     // method, and it can never be changed by an override.
1361     if (vtable_index == Method::nonvirtual_vtable_index) {
1362       assert(resolved_method->can_be_statically_bound(), "cannot override this method");
1363       selected_method = resolved_method;
1364     } else {
1365       selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index));
1366     }
1367   }
1368 
1369   // check if method exists
1370   if (selected_method.is_null()) {
1371     ResourceMark rm(THREAD);
1372     THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
1373               Method::name_and_sig_as_C_string(resolved_klass,
1374                                                resolved_method->name(),
1375                                                resolved_method->signature()));
1376   }
1377 
1378   // check if abstract
1379   if (check_null_and_abstract && selected_method->is_abstract()) {
1380     ResourceMark rm(THREAD);
1381     THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
1382               Method::name_and_sig_as_C_string(resolved_klass,
1383                                                selected_method->name(),
1384                                                selected_method->signature()));
1385   }
1386 
1387   if (log_develop_is_enabled(Trace, vtables)) {
1388     trace_method_resolution("invokevirtual selected method: receiver-class:",
1389                             recv_klass, resolved_klass, selected_method,
1390                             false, vtable_index);
1391   }
1392   // setup result
1393   result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
1394 }
1395 
1396 void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, Klass* recv_klass,
1397                                           const LinkInfo& link_info,
1398                                           bool check_null_and_abstract, TRAPS) {
1399   // throws linktime exceptions
1400   methodHandle resolved_method = linktime_resolve_interface_method(link_info, CHECK);
1401   runtime_resolve_interface_method(result, resolved_method,link_info.resolved_klass(),
1402                                    recv, recv_klass, check_null_and_abstract, CHECK);
1403 }
1404 


1420                                                     Klass* recv_klass,
1421                                                     bool check_null_and_abstract, TRAPS) {
1422   // check if receiver exists
1423   if (check_null_and_abstract && recv.is_null()) {
1424     THROW(vmSymbols::java_lang_NullPointerException());
1425   }
1426 
1427   // check if receiver klass implements the resolved interface
1428   if (!recv_klass->is_subtype_of(resolved_klass)) {
1429     ResourceMark rm(THREAD);
1430     char buf[200];
1431     jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s",
1432                  recv_klass->external_name(),
1433                  resolved_klass->external_name());
1434     THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
1435   }
1436 
1437   // do lookup based on receiver klass
1438   // This search must match the linktime preparation search for itable initialization
1439   // to correctly enforce loader constraints for interface method inheritance
1440   methodHandle sel_method = lookup_instance_method_in_klasses(recv_klass,
1441                                                   resolved_method->name(),
1442                                                   resolved_method->signature(), CHECK);
1443   if (sel_method.is_null() && !check_null_and_abstract) {
1444     // In theory this is a harmless placeholder value, but
1445     // in practice leaving in null affects the nsk default method tests.
1446     // This needs further study.
1447     sel_method = resolved_method;
1448   }
1449   // check if method exists
1450   if (sel_method.is_null()) {
1451     ResourceMark rm(THREAD);
1452     THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
1453                    Method::name_and_sig_as_C_string(recv_klass,
1454                                                     resolved_method->name(),
1455                                                     resolved_method->signature()));
1456   }
1457   // check access
1458   // Throw Illegal Access Error if sel_method is not public.
1459   if (!sel_method->is_public()) {
1460     ResourceMark rm(THREAD);
1461     THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
1462               Method::name_and_sig_as_C_string(recv_klass,
1463                                                sel_method->name(),
1464                                                sel_method->signature()));
1465   }
1466   // check if abstract
1467   if (check_null_and_abstract && sel_method->is_abstract()) {
1468     ResourceMark rm(THREAD);
1469     THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
1470               Method::name_and_sig_as_C_string(recv_klass,
1471                                                sel_method->name(),
1472                                                sel_method->signature()));
1473   }
1474 
1475   if (log_develop_is_enabled(Trace, itables)) {
1476     trace_method_resolution("invokeinterface selected method: receiver-class:",
1477                             recv_klass, resolved_klass, sel_method, true);
1478   }
1479   // setup result
1480   if (!resolved_method->has_itable_index()) {
1481     int vtable_index = resolved_method->vtable_index();
1482     assert(vtable_index == sel_method->vtable_index(), "sanity check");
1483     result.set_virtual(resolved_klass, recv_klass, resolved_method, sel_method, vtable_index, CHECK);
1484   } else {
1485     int itable_index = resolved_method()->itable_index();
1486     result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, itable_index, CHECK);
1487   }
1488 }
1489 
1490 
1491 methodHandle LinkResolver::linktime_resolve_interface_method_or_null(
1492                                                  const LinkInfo& link_info) {
1493   EXCEPTION_MARK;
1494   methodHandle method_result = linktime_resolve_interface_method(link_info, THREAD);
1495   if (HAS_PENDING_EXCEPTION) {
1496     CLEAR_PENDING_EXCEPTION;
1497     return methodHandle();
1498   } else {
1499     return method_result;
1500   }
1501 }
1502 
1503 methodHandle LinkResolver::linktime_resolve_virtual_method_or_null(
1504                                                  const LinkInfo& link_info) {
1505   EXCEPTION_MARK;
1506   methodHandle method_result = linktime_resolve_virtual_method(link_info, THREAD);


1755                                         int pool_index,
1756                                         Handle bootstrap_specifier,
1757                                         Symbol* method_name, Symbol* method_signature,
1758                                         Klass* current_klass,
1759                                         TRAPS) {
1760   // JSR 292:  this must resolve to an implicitly generated method MH.linkToCallSite(*...)
1761   // The appendix argument is likely to be a freshly-created CallSite.
1762   Handle       resolved_appendix;
1763   Handle       resolved_method_type;
1764   methodHandle resolved_method =
1765     SystemDictionary::find_dynamic_call_site_invoker(current_klass,
1766                                                      pool_index,
1767                                                      bootstrap_specifier,
1768                                                      method_name, method_signature,
1769                                                      &resolved_appendix,
1770                                                      &resolved_method_type,
1771                                                      THREAD);
1772   Exceptions::wrap_dynamic_exception(CHECK);
1773   result.set_handle(resolved_method, resolved_appendix, resolved_method_type, THREAD);
1774   Exceptions::wrap_dynamic_exception(CHECK);



































1775 }


1326                                                   Klass* recv_klass,
1327                                                   bool check_null_and_abstract,
1328                                                   TRAPS) {
1329 
1330   // setup default return values
1331   int vtable_index = Method::invalid_vtable_index;
1332   methodHandle selected_method;
1333 
1334   // runtime method resolution
1335   if (check_null_and_abstract && recv.is_null()) { // check if receiver exists
1336     THROW(vmSymbols::java_lang_NullPointerException());
1337   }
1338 
1339   // Virtual methods cannot be resolved before its klass has been linked, for otherwise the Method*'s
1340   // has not been rewritten, and the vtable initialized. Make sure to do this after the nullcheck, since
1341   // a missing receiver might result in a bogus lookup.
1342   assert(resolved_method->method_holder()->is_linked(), "must be linked");
1343 
1344   // do lookup based on receiver klass using the vtable index
1345   if (resolved_method->method_holder()->is_interface()) { // default or miranda method
1346     vtable_index = vtable_index_of_interface_method(resolved_klass, resolved_method);

1347     assert(vtable_index >= 0 , "we should have valid vtable index at this point");
1348 
1349     selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index));
1350   } else {
1351     // at this point we are sure that resolved_method is virtual and not
1352     // a default or miranda method; therefore, it must have a valid vtable index.
1353     assert(!resolved_method->has_itable_index(), "");
1354     vtable_index = resolved_method->vtable_index();
1355     // We could get a negative vtable_index for final methods,
1356     // because as an optimization they are never put in the vtable,
1357     // unless they override an existing method.
1358     // If we do get a negative, it means the resolved method is the the selected
1359     // method, and it can never be changed by an override.
1360     if (vtable_index == Method::nonvirtual_vtable_index) {
1361       assert(resolved_method->can_be_statically_bound(), "cannot override this method");
1362       selected_method = resolved_method;
1363     } else {
1364       selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index));
1365     }
1366   }
1367 
1368   // check if method exists
1369   if (selected_method.is_null()) {
1370     throw_abstract_method_error(resolved_method, recv_klass, CHECK);




1371   }
1372 
1373   // check if abstract
1374   if (check_null_and_abstract && selected_method->is_abstract()) {
1375     // Pass arguments for generating a verbose error message.
1376     throw_abstract_method_error(resolved_method, selected_method, recv_klass, CHECK);



1377   }
1378 
1379   if (log_develop_is_enabled(Trace, vtables)) {
1380     trace_method_resolution("invokevirtual selected method: receiver-class:",
1381                             recv_klass, resolved_klass, selected_method,
1382                             false, vtable_index);
1383   }
1384   // setup result
1385   result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
1386 }
1387 
1388 void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, Klass* recv_klass,
1389                                           const LinkInfo& link_info,
1390                                           bool check_null_and_abstract, TRAPS) {
1391   // throws linktime exceptions
1392   methodHandle resolved_method = linktime_resolve_interface_method(link_info, CHECK);
1393   runtime_resolve_interface_method(result, resolved_method,link_info.resolved_klass(),
1394                                    recv, recv_klass, check_null_and_abstract, CHECK);
1395 }
1396 


1412                                                     Klass* recv_klass,
1413                                                     bool check_null_and_abstract, TRAPS) {
1414   // check if receiver exists
1415   if (check_null_and_abstract && recv.is_null()) {
1416     THROW(vmSymbols::java_lang_NullPointerException());
1417   }
1418 
1419   // check if receiver klass implements the resolved interface
1420   if (!recv_klass->is_subtype_of(resolved_klass)) {
1421     ResourceMark rm(THREAD);
1422     char buf[200];
1423     jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s",
1424                  recv_klass->external_name(),
1425                  resolved_klass->external_name());
1426     THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
1427   }
1428 
1429   // do lookup based on receiver klass
1430   // This search must match the linktime preparation search for itable initialization
1431   // to correctly enforce loader constraints for interface method inheritance
1432   methodHandle selected_method = lookup_instance_method_in_klasses(recv_klass,
1433                                                   resolved_method->name(),
1434                                                   resolved_method->signature(), CHECK);
1435   if (selected_method.is_null() && !check_null_and_abstract) {
1436     // In theory this is a harmless placeholder value, but
1437     // in practice leaving in null affects the nsk default method tests.
1438     // This needs further study.
1439     selected_method = resolved_method;
1440   }
1441   // check if method exists
1442   if (selected_method.is_null()) {
1443     // Pass arguments for generating a verbose error message.
1444     throw_abstract_method_error(resolved_method, recv_klass, CHECK);



1445   }
1446   // check access
1447   // Throw Illegal Access Error if selected_method is not public.
1448   if (!selected_method->is_public()) {
1449     ResourceMark rm(THREAD);
1450     THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
1451               Method::name_and_sig_as_C_string(recv_klass,
1452                                                selected_method->name(),
1453                                                selected_method->signature()));
1454   }
1455   // check if abstract
1456   if (check_null_and_abstract && selected_method->is_abstract()) {
1457     throw_abstract_method_error(resolved_method, selected_method, recv_klass, CHECK);




1458   }
1459 
1460   if (log_develop_is_enabled(Trace, itables)) {
1461     trace_method_resolution("invokeinterface selected method: receiver-class:",
1462                             recv_klass, resolved_klass, selected_method, true);
1463   }
1464   // setup result
1465   if (!resolved_method->has_itable_index()) {
1466     int vtable_index = resolved_method->vtable_index();
1467     assert(vtable_index == selected_method->vtable_index(), "sanity check");
1468     result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
1469   } else {
1470     int itable_index = resolved_method()->itable_index();
1471     result.set_interface(resolved_klass, recv_klass, resolved_method, selected_method, itable_index, CHECK);
1472   }
1473 }
1474 
1475 
1476 methodHandle LinkResolver::linktime_resolve_interface_method_or_null(
1477                                                  const LinkInfo& link_info) {
1478   EXCEPTION_MARK;
1479   methodHandle method_result = linktime_resolve_interface_method(link_info, THREAD);
1480   if (HAS_PENDING_EXCEPTION) {
1481     CLEAR_PENDING_EXCEPTION;
1482     return methodHandle();
1483   } else {
1484     return method_result;
1485   }
1486 }
1487 
1488 methodHandle LinkResolver::linktime_resolve_virtual_method_or_null(
1489                                                  const LinkInfo& link_info) {
1490   EXCEPTION_MARK;
1491   methodHandle method_result = linktime_resolve_virtual_method(link_info, THREAD);


1740                                         int pool_index,
1741                                         Handle bootstrap_specifier,
1742                                         Symbol* method_name, Symbol* method_signature,
1743                                         Klass* current_klass,
1744                                         TRAPS) {
1745   // JSR 292:  this must resolve to an implicitly generated method MH.linkToCallSite(*...)
1746   // The appendix argument is likely to be a freshly-created CallSite.
1747   Handle       resolved_appendix;
1748   Handle       resolved_method_type;
1749   methodHandle resolved_method =
1750     SystemDictionary::find_dynamic_call_site_invoker(current_klass,
1751                                                      pool_index,
1752                                                      bootstrap_specifier,
1753                                                      method_name, method_signature,
1754                                                      &resolved_appendix,
1755                                                      &resolved_method_type,
1756                                                      THREAD);
1757   Exceptions::wrap_dynamic_exception(CHECK);
1758   result.set_handle(resolved_method, resolved_appendix, resolved_method_type, THREAD);
1759   Exceptions::wrap_dynamic_exception(CHECK);
1760 }
1761 
1762 // Selected method is abstract.
1763 void LinkResolver::throw_abstract_method_error(const methodHandle& resolved_method,
1764                                                const methodHandle& selected_method,
1765                                                Klass *recv_klass, TRAPS) {
1766   Klass *resolved_klass = resolved_method->method_holder();
1767   ResourceMark rm;
1768   stringStream ss;
1769 
1770   if (recv_klass != NULL) {
1771     ss.print("Receiver class %s does not define or inherit an "
1772              "implementation of the",
1773              recv_klass->external_name());
1774   } else {
1775     ss.print("Missing implementation of");
1776   }
1777 
1778   assert(resolved_method.not_null(), "Sanity");
1779   ss.print(" resolved method %s%s%s%s of %s %s.",
1780            resolved_method->is_abstract() ? "abstract " : "",
1781            resolved_method->is_private()  ? "private "  : "",
1782            resolved_method->name()->as_C_string(),
1783            resolved_method->signature()->as_C_string(),
1784            resolved_klass->external_kind(),
1785            resolved_klass->external_name());
1786 
1787   if (selected_method.not_null() && !(resolved_method == selected_method)) {
1788     ss.print(" Selected method is %s%s%s.",
1789              selected_method->is_abstract() ? "abstract " : "",
1790              selected_method->is_private()  ? "private "  : "",
1791              selected_method->name_and_sig_as_C_string());
1792   }
1793 
1794   THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string());
1795 }
< prev index next >